Постигая Agile Грин Дженнифер
Истории небольшие и не связаны между собой. Команда может быстро создать историю и передать ее клиенту, поэтому, если программное обеспечение окажется неудачным, она в сотрудничестве с пользователями сможет внести необходимые изменения.
Принятие ответственности
Программист прочитал карточку задачи, оценил, сколько времени потребуется на выполнение работы, и тем самым взял всю ответственность на себя.
Коммуникация
Записывая историю на языке, понятном для пользователя, проще определить приоритеты в работе.
Качество
Обдумывая заранее, как вы будете тестировать историю, вы способствуете поставке продукта высокого качества.
Благодаря тому, что вы уже понимаете, как работают пользовательские истории и как применяют их проектные команды, вы сможете отталкиваться от них, чтобы лучше понять перечисленные принципы.
Обе методологии придают большое значение обратной связи. Мы уже видели, как Scrum использует петли обратной связи, чтобы получить непрерывную коммуникацию между командой и заказчиком. Команды, применяющие эти методологии, разделяют очень похожие ценности – открытость (Scrum) и коммуникацию (ХР). Они сходным образом воспринимают способы общения разработчиков в команде.
Но XP придает гораздо большее значение обратной связи. XP-команды нацелены на очень короткие итерации (недельный цикл) для улучшения качества обратной связи и укорочения петли. Изучая Scrum, мы узнали, что для эффективной итерации команда должна активно интересоваться потребностями пользователей и понимать, что для них ценно. Чтобы сделать петли обратной связи короче, программисты постоянно анализируют ход проекта.
Если возникает проблема, то команда будет ее обсуждать. Осмотическая коммуникация, происходящая тогда, когда люди сидят рядом, помогает распространять эту обратную связь внутри команды. Если совместить все эти приемы, то команда может достичь в своей работе состояния потока. Этот XP-принцип говорит о том, что прямой и эффективный способ работы над проектом заключается в обеспечении постоянного потока функционального и высококачественного ПО.
Рис. 6.6. Когда мышление команды соответствует XP, ее практики помогают эффективнее создавать программное обеспечение
Различных ХР-практик очень много – размещение рядом друг с другом, осмотическая коммуникация, петли обратной связи, коммуникация, рефлексия. Их объединяют, чтобы помочь командам найти эффективный путь выполнения проекта. Но поток происходит только тогда, когда много компонентов работают вместе: методы, принципы, идеи и, прежде всего, хорошие архитектура программного обеспечения и кодирование. Когда команды достигают состояния потока, они реализуют бесперебойную поставку программного обеспечения. Активная коммуникация и постоянная обратная связь приводят к тому, что люди начинают видеть узкие места на пути создания ПО и учатся обходить препятствия как единая команда. Они ликвидируют эти узкие места, и поток становится свободным.
Этого нельзя достичь в одночасье. Команда должна затратить время не только на создание программного обеспечения, но и на обсуждение того, как она его пишет, и изучение, как каждый принцип и практика могут помочь улучшить работу. Кроме того, принцип маленьких шагов даст команде ощущение комфорта при постановке целей, так же как короткие петли обратной связи ведут к потоку. Методология как целое становится дорожной картой: команда может добавлять практики по одной, руководствуясь ценностями и принципами при каждом внедрении. Например, одну неделю они могли бы искать способ увеличить рефлексию или улучшить свое окружение, сидя вместе, или повысить эффективность работы в парах. Пока вся команда предпринимает шаги в правильном направлении, она знает, что улучшает планирование, отслеживание и выполнение проекта. А это значит, что она с каждым днем становится совершеннее – не только работая с XP, но и создавая программное обеспечение.
Ключевые моментыXP имеет пять ценностей, которые помогают командам сформировать правильное мышление и избегать результата «лучше-чем-ничего».
Коммуникация как ХР-ценность означает, что каждый член команды в курсе дел коллег и постоянно с ними общается.
XP-команды ценят простоту, пишут четкие и ясные решения, избегают сложностей.
Благодаря постоянному тестированию и интеграции XP-команды создают петли обратной связи, помогающие поддерживать высокое качество.
Члены XP-команд имеют мужество принять лучшее решение, которое потребует большего объема работы в краткосрочной перспективе, чтобы в дальнейшем было проще обслуживать код.
Каждый член XP-команды заслуживает уважения коллег, менеджеров и пользователей.
Так с чего же начать? Как узнать, какие шаги делать в первую очередь?
Многие команды, впервые сталкивающиеся с ХР, задают эти вопросы, но на них нет однозначного ответа. Он зависит от конкретных проблем. На первой странице этой главы приведена цитата, в которой говорится о том, как люди ненавидят перемены. Не стоит это недооценивать.
Принятие ХР означает, что вы меняете способ разработки программного обеспечения. Восторг сотрудников в отношении новой практики улетучится, как только люди поймут, что работу надо выполнять не так, как прежде.
Итак, каким должен быть первый шаг? Если вы рассматриваете ХР в качестве инструмента для решения проблем, то логично предположить, что они у вас есть. Каковы эти проблемы? Какие ХР-практики могут помочь вам их решить?
Если проблемы связаны с ошибками, то попробуйте начать с разработки через тестирование. А может, члены вашей команды не общаются между собой или удивляются изменению требований? Тогда добавьте истории, но пробуйте практики по одной – и не только для галочки. Соберитесь всей командой и поговорите о ценностях и принципах ХР. Убедитесь, что все понимают, чего вы пытаетесь добиться при помощи этой практики. Если каждый человек понимает, в чем заключается проблема, которую вы пытаетесь решить, и как она влияет на него самого, то вы сможете оценить, насколько хорошо эта практика будет работать.
Это поможет вам найти решение, но, что более важно, каждый человек в команде поймет, как эта практика улучшает его жизнь. И у них не возникнет чувства, что они тратят свое время впустую (из-за чего команды порой перестают использовать практики).
Меня беспокоит, что я не понимаю, как применить парное программирование к моему проекту. Что оно может дать?
Когда команда пытается внедрить XP, но в конце концов возвращается к прежним методам работы, практика парного программирования, как канарейка в угольной шахте, погибает первой. Так случается часто, потому что эта практика наиболее явно демонстрирует разницу между мышлением команды и ценностями ХР. Поэтому если вы не видите смысла в парном программировании, то обдумайте ценности ХР заново.
Коммуникация
Считаете ли вы нормой общение с коллегой в ходе программирования? Как вы отнесетесь к тому, что в этот момент с вами заведут разговор? Допускаете ли вы, чтобы ваш код обсуждали без вас?
Простота
Считаете ли вы нормальным, если кто-то говорит, что код, который вы только что написали, очень сложный? Готовы ли вы выделить время, чтобы исправить его немедленно, или оставите комментарий «сделать» либо «решить позднее»? А если поджимают сроки, вы все равно готовы заняться упрощением кода?
Обратная связь
Хорошо ли вы себя чувствуете, если кто-то говорит вам – возможно, проявляя бестактность, что характерно для многих программистов, – что ваш код не очень хорош?
Мужество
Решаетесь ли вы, просмотрев чей-то код, указать на ошибки, даже если это спорный вопрос? Спокойно ли вы воспринимаете свои ошибки в оценке чужого кода? Нормально ли вы воспринимаете ситуацию, когда допускаете ошибки на глазах коллег, которые указывают вам на них? А если этот человек пользуется вашим уважением или выше вас по должности?
Уважение
Когда кто-то говорит, что ваш код не слишком хорош, готовы ли вы прислушаться к этому мнению и пересмотреть свою работу, чтобы понять, кто прав? Не затаите ли вы обиду?
Если в вашей команде не все гладко с реализацией этих принципов, то их анализ поможет вам понять, что необходимо делать, прежде чем внедрять ХР. Какой из приведенных выше вопросов беспокоит всех больше всего? Обсудите это, чтобы выяснить, что создает дискомфорт в команде. Подумайте, что нужно сделать, чтобы избавиться от него.
Существует наихудший сценарий, когда образ мыслей не позволяет команде использовать парное программирование, но дает внедрить какую-то иную практику XP. Однако недостаточно просто внедрить практику, кажущуюся бессмысленной. Нужно убедиться, что вся ваша команда обсуждает ХР-ценности и серьезно относится к принципам. Есть надежда, что спустя некоторое время вы вернетесь к парному программированию и обнаружите, что ваше мышление изменилось благодаря маленьким шагам, сделанным в применении других практик.
Почему программисты должны писать все эти тесты? В моей команде нет лишних сотрудников, чтобы сидеть и отлавливать ошибки. Разве не дешевле нанять тестеров?
Разработка через тестирование – это не просто добавление тестов и проверка того, что они выполняются. Чувствуете ли вы дискомфорт от идеи разработки через тестирование? Если да, то это показатель того, что вам нужно пересмотреть свои взгляды на ценности и принципы. Вероятно, вы обнаружите, что не поняли один из них. Может быть, у вас проблема с принципом качества, который означает, что каждый член команды отвечает за качество проекта. Вы не можете просто «перекинуть» код на этап тестирования и назначить ответственного за поиск ошибок. Возможно, вас тревожит избыточность – кажется, что эти тесты добавляют дополнительный, потенциально дублирующий код. Потратьте немного времени на переосмысление принципов и ценностей и попытайтесь сформулировать, что именно вам не вполне понятно.
Действительно, написание модульных тестов требует времени, и очень часто разработчики считают, что это напрасный труд[55]. Но самое забавное происходит, когда программисты все-таки начинают заниматься разработкой через тестирование. В какой-то момент модульный тест дает сбой, тем самым выявляя маленькую, но неприятную ошибку, которая потом могла бы отнять массу времени. Несколько подобных случаев переубедят любого скептика. Когда это происходит, многие agile-разработчики говорят, что вы «заражаетесь тестами», и разработка через тестирование становится естественным способом создания программного обеспечения.
Необходимо помнить еще об одном: в разработке через тестирование гораздо больше смысла, чем кажется на первый взгляд. В главе 7 вы узнаете, что написание модульных тестов до создания кода может иметь огромное влияние на то, как команда разрабатывает программное обеспечение. Те, кто эффективно использует разработку через тестирование, создают более качественное ПО не только потому, что отлавливают ошибки, но и благодаря тому, что начинают думать иначе.
Все еще сомневаетесь? Это нормально. Вам просто надо найти другой подход к XP. К счастью, есть много иных методов, с которых можно начать. Как и в случае с парным программированием, если вам не удается убедить себя и команду, что разработка через тестирование – это верный путь, то попробуйте другой метод.
Я программист, и все это кажется мне чем-то неопределенным. Обычно я получаю задание, поэтому представляю, чем должен заниматься. Откуда же я узнаю, что мне делать дальше?
Если вы привыкли работать по плану-графику или диаграмме Ганта, то ХР-подход к ежедневному планированию может показаться вам необычным. Ежедневно вы получаете список задач, каждую из которых нужно выполнить и после этого отметить галочкой. Так работать удобно, потому что вы всегда видите свой прогресс. Руководителю и менеджеру проекта это также подходит – они легко могут видеть состояние проекта по проставленным галочкам.
Разработчику, привыкшему к такому режиму, поначалу трудно приспособиться к зрелой ХР-команде. Потому что в командно-административной среде кто-то уже проанализировал исходные требования и составил на их основе список задач, которые команда должна выполнить. Это задает строгий порядок действий каждого программиста, поскольку все решения были приняты в начале проекта.
XP-команды не занимаются предварительным планированием. Они обсуждают темы и истории при планировании квартального цикла, но работают по очень коротким, недельным итерациям. Индивидуальные задания планируются только на ближайшую неделю. В этом и заключается «экстремальность» экстремального программирования – в принятии решения в последний ответственный момент. И разработчику, привыкшему, чтобы все было запланировано заранее, кажется, что решения принимаются слишком поздно.
Есть еще одна ситуация, когда ХР-команда может вызвать ощущение «дезорганизации» у тех, кто раньше использовал гораздо более жесткое планирование: пары постоянно меняются и люди не определяют заранее, кто какое задание должен делать. Решение о том, кому выполнять ту или иную работу, принимается непосредственно перед ее началом. Это отличается от методов scrum-команд, у которых есть ежедневные совещания, оценивающие ход работ по спринту, и назначение задач происходит способом самоорганизации. Поскольку XP-команда имеет короткие итерации и петли обратной связи, она может «свалить» свои задачи в кучу, и, когда пара готова к следующему заданию, она просто вытягивает его оттуда.
Разве можно ждать хорошей работы от команды, если каждая пара наобум выбирает задание? Может быть, лучше планировать работу, учитывая навыки каждого программиста?
Нет. И это еще одна область, в которой XP помогает команде совершенствоваться. В начале недельного цикла команда выбирает истории, которые собирается делать, и разбивает их на задачи. Поскольку разработка ведется итеративно, в конце цикла они поставляют работающее программное обеспечение, которое действительно сделано, а все частично завершенные истории переносятся в следующий цикл. Но они не планируют, кто какую задачу будет делать. Вместо этого задачи «сваливаются» в кучу, ставятся в очередь или организуются иным образом. После того как пара заканчивает текущее задание, она выбирает следующее из очереди.
Значит ли это, что существует правило, будто люди должны выбирать следующее задание случайным образом, даже если в команде есть тот, кто справится с ним лучше? Конечно, нет. Члены команды не роботы. Они будут делать то, на что способны, и принимать самые правильные решения в процессе работы. Возможно, стоит подбирать пары таким образом, чтобы один участник имел глубокие знания в определенной области, а другой стремился в ней усовершенствоваться. Тогда в следующий раз, когда появится задание, требующее аналогичного навыка, у команды будет из кого выбирать, потому что нужные знания есть уже у двух человек.
Существует веская причина, по которой XP не имеет закрепленных ролей. Вот что Кент Бек говорит об этом в своей книге Extreme Programming Explained: Embrace Change.
После того как между членами команды устанавливаются новые, уважительные отношения, закрепленные роли мешают им действовать наилучшим образом. Программисты могут писать историю, если сейчас это полезнее. Менеджеры проектов могут предложить архитектурные улучшения, если они видят, как их сделать.
Это отражает два важных ХР-принципа.
Принятие ответственности
После того как пара берется за задачу, она обязана завершить ее. Если она столкнется с проблемами, то сделает все возможное, чтобы справиться с ними. Но эти программисты попросят помощи у команды, даже если это может задеть их самолюбие. (Хотелось бы надеяться, что, поскольку они работают вдвоем, кто-то услышит их дискуссию и сам предложит помощь.)
Возможность
Каждая новая задача – это возможность для человека научиться еще чему-то, выполняя при этом свою работу. Если есть технология, которую кто-то не знает, то ее изучение становится частью задачи. Это помогает распространять знания внутри команды и открывает больше возможностей на будущее.
Есть еще одна идея, применимая в такой ситуации: коллективное владение. Помимо 13 основных XP-практик существует также 11 вытекающих из них практик-следствий.
Истинная вовлеченность клиентов
Реальное вовлечение клиентов в квартальные и еженедельные сессии планирования и учет их мнений.
Инкрементальное развертывание
Развертывание небольших частей системы по отдельности, а не «одним ударом» (с верой в то, что внедрение можно выполнить таким путем).
Целостность команды
Объединение эффективных команд.
Сокращение команд
Когда команда улучшается, она может выполнять работу быстрее. Но вместо того чтобы увеличивать объем еженедельной работы, исключите из команды одного человека (и используйте его для переноса ХР-культуры в другую команду).
Анализ первопричин
Когда что-то идет не так, выясните, в чем дело и что привело к этому, после чего устраните проблему так, чтобы она больше не возникала.
Общий код
Каждый человек в команде чувствует себя комфортно, работая с любой частью кода, и все коллективно владеют кодом.
Код и тесты
Команда поддерживает только код и тесты, документация генерируется автоматически из исходного кода, и история сохраняет жизнеспособность благодаря передаче из уст в уста (потому что люди редко открывают пыльные папки со старыми планами).
Единая база кода
Не поддерживайте несколько версий кода.
Ежедневное развертывание
Развертывайте новые версии в производственную среду каждый день.
Согласованный объем контракта
Как принято в консалтинговых компаниях, вместо того чтобы фиксировать объем и время переговоров (часто жертвуя качеством, чтобы уложиться в срок), фиксируйте время и регулярно договаривайтесь об объемах.
Плата за использование
Это еще одна практика, заимствованная из консалтинга, – вместо того чтобы выставлять счет за разработку, взимайте плату с клиента за использование системы. Это позволяет получать в режиме реального времени постоянную обратную связь и знать, какие функции востребованы, а какие нет.
В этой книге больше не будут упоминаться практики-следствия, но одна из них – общий код – имеет особое значение. В ХР-команде любой ее член – даже менеджер проекта – имеет право вносить изменения в код. Потому что он принадлежит всем. Это означает, что если обнаружится ошибка, то исправление может внести любой член команды, а не только тот, кто ее допустил. Такой подход отличается от работы традиционных команд, где каждый ответственен за собственный кусок кода.
(Существует еще одна практика-следствие, о которой мы будем много говорить, – анализ первопричин и метод пяти «почему», который поможет уловить за внешними проявлениями суть проблемы. Мы вернемся к этому в главе 8.)
Разрушение барьеров владения кодом помогает объединить команду, потому что при возникновении проблемы все чувствуют ответственность за ее решение. Поэтому каждый член команды отвечает за весь код и соответственно способен решить любую задачу в очереди или, по крайней мере, научиться ее решать. Команда понимает, что процесс обучения – это часть проекта и на него стоит тратить свое время.
Практик-следствий действительно 11? Почему их так много?
Если количество практик в XP кажется вам огромным, то это признак того, что вы формально относитесь к этой методологии. Ранее мы видели, что такое мышление может привести вас только к результату «лучше-чем-ничего». Практики-следствия существуют потому, что помогают решать проблемы, с которыми сталкиваются команды во время создания лучшего программного обеспечения. Если вы беспокоитесь о том, как сможете выполнять все эти практики одновременно, значит, вы склонны к формальному подходу к ХР. Помните ХР-принцип маленьких шагов: если вы тратите время, чтобы понять, какие практики нужны вам и вашей команде, то будет проще включить их в свою деятельность и постепенно улучшать совместную работу.
В главе 7 вы узнаете о том, как XP-практики работают вместе и оказывают значительное влияние на то, как команда проектирует и создает код. Пока вы будете ее читать, постарайтесь найти варианты совместной работы практик и понять, как они при этом взаимно усиливаются. Это позволит вам выйти за рамки формального мышления и воспринять ХР как целостную систему.
Предлагаем несколько вариантов действий, которые вы можете предпринять уже сегодня (самостоятельно или вместе с командой).
• Попробуйте парное программирование, даже если на первый взгляд оно кажется вам немного странным. Нет нужды брать на себя обязательство делать это всегда, просто позанимайтесь этим несколько часов и оцените впечатления. Возможно, вы поймете, что такая работа намного удобнее, чем кажется!
• Если вы разработчик, попробуйте непрерывную интеграцию. Вам даже не нужно привлекать к этому остальную команду (пока). В следующий раз, когда вы достигнете ключевой точки, в чем бы она ни заключалась, возьмите последний код из хранилища контроля версий, поместите его в вашу песочницу и проведите тестирование, чтобы убедиться: код интегрирован. Сделайте это снова через несколько часов. Насколько часто вы сталкиваетесь с проблемой интеграции, которую легко решить сейчас, но гораздо сложнее позднее?
• Попробуйте разработку через тестирование. В следующий раз, когда вы создаете новый класс (модуль или подпрограмму – все, что считается единицей в языке, который вы используете), сначала напишите модульный тест. Не беспокойтесь, если он не будет охватывать все возможные случаи. Создайте простой работающий тест. Возможно, вам придется потратить немного времени на изучение того, как модульное тестирование работает с языком, – это также полезное упражнение.
Ниже перечислены ресурсы, которые помогут вам узнать больше об идеях, описанных в этой главе.
• Вы можете узнать больше о методах, ценностях и принципах XP в книге Кента Бека и Синтии Андрес Extreme Programming Explained: Embrace Change (Addison-Wesley, 2004).
• Узнайте больше о модульном тестировании и разработке через тестирование в книге Энди Ханта и Дэйва Томаса Pragmatic Unit Testing (Pragmatic Bookshelf: Java version 2003, C# version 2007).
Здесь мы предлагаем советы для agile-коучей, помогающих своей команде разрабатывать идеи этой главы.
• Это один из самых сложных аспектов agile-коучинга, особенно для agile-тренеров, которые не имеют опыта программирования. Сосредоточьтесь на ХР-ценностях и принципах и помогите команде выяснить, как они влияют на код.
• Команде легко потерять мужество и уважение. Помогите найти примеры, когда они колебались, сообщать ли кому-то вне команды реальное состояние качества кода. Например, подправляла ли команда когда-нибудь демоверсию, чтобы обойти известные ей ошибки. Меняла ли она отчет об ошибке, чтобы та казалась менее серьезной, чем на самом деле? Помогите ей найти способы, чтобы было легче делиться такой информацией.
• Как найти лучшие возможности для коммуникации команды? Помогите ей создать информационное табло.
Глава 7. ХР, простота и инкрементальная архитектура
Я не великий программист, я просто хороший программист с замечательными привычками.
Кент Бек, создатель ХР
Цели XP выходят за рамки простого стремления научить команду работать лучше. Масштабная цель XP-практик, ценностей и принципов – помочь командам создавать программное обеспечение, которое можно легко изменять и расширять, а также работать, планировать и расти вместе в среде, легко принимающей изменения.
Внедрение ХР означает больше, чем просто использование парного программирования для постоянной проверки кода или разработки через тестирование для увеличения тестового покрытия. Повышение качества и улучшение отношений с коллегами – это замечательные побочные эффекты XP, и они помогают достичь основной цели. Эти практики изменяют технологию создания ПО, но не вносят кардинальных изменений в его проектирование.
Повторим еще раз: важная цель XP – это программное обеспечение, которое может быть легко изменено. Команды примут изменения охотнее, если создаваемый ими программный продукт несложно изменять. Это оказывает глубокое влияние на подход хорошей XP-команды к разработке и проектированию программ.
Здесь также следует отметить один из ключевых моментов приобретения правильного ХР-мышления: искреннюю веру в то, что практики, изученные в главе 6, такие как разработка через тестирование, парное программирование и временной запас, помогают вам и вашей команде изменить подход к разработке ПО. Игнорирование этих практик может привести к созданию некачественного, трудно изменяемого исходного кода.
В этой главе вы узнаете, как талантливые программисты иногда все же создают код с серьезными проблемами в нем самом и архитектуре. Вы изучите три оставшихся основных XP-практики и то, как они помогают избегать упомянутых проблем. Вы узнаете о многих замечательных привычках, которые появляются у членов ХР-команд (подобных той, о которой говорится в цитате Кента Бека в начале главы). Мы также расскажем, как все XP-практики формируют экосистему, в которой создается лучший, легкий в обслуживании, гибкий и изменяемый код.
Описание: команда занимается разработкой фантазийного баскетбольного сайтаДжастин – первый разработчик
Даниэль – второй разработчик
Бриджит – их менеджер проекта
Акт IV. Работа в сверхурочное время, часть 2: снова сверхурочные
Джастин обычно старался уходить из офиса с таким расчетом, чтобы успеть к поезду, отходящему в 17:42. Почему-то это случалось редко. Сегодняшний день не стал исключением. Поздним уходам всегда предшествовала одна и та же ситуация: примерно за час до окончания рабочего дня он приступал к исправлению небольшой ошибки или внесению незначительной настройки. Но маленькие изменения непонятным образом превращались в большую работу.
Это всегда происходило по одной и той же схеме. Внеся запланированное изменение, Джастин обнаруживал, что необходимо подправить и другую часть кода. Он шел дальше и вносил второе изменение. Но это вмешательство влекло за собой необходимость корректировать третью и четвертую части кода. Одно из этих изменений могло, в свою очередь, потребовать, чтобы он перешел к еще одной части исходного кода и т. д. Иногда, к тому времени, когда он заканчивал вносить цепочку исправлений, он уже забывал, зачем делалась первая правка.
Однажды изменения оказались такими кардинальными, что он просто не мог их внести. Он поговорил с Даниэль и Бриджит, и они решили, что требуемые изменения были настолько рискованными, что могли дестабилизировать код. Ситуация оказалась деморализующей: была потрачена масса времени на внесение изменений, а потом все пришлось возвращать в исходное состояние.
Сегодняшний вечер ничем не отличался от предыдущих и развивался по обычной схеме: изменения вызывали изменения. Джастин вспомнил, как говорил Даниэль: «Я обещал своей девушке, что буду дома рано, поэтому просто собираюсь сделать последний кусок задания на сегодня». Надо было всего-то добавить опцию в раскрывающемся списке на странице «Настройки». Это было просто, точнее, ему так казалось пять часов назад.
Если бы он знал, что дело настолько затянется, то поработал бы вечером из дома. Или вообще оставил бы это на потом.
Джастин пытался исправить раскрывающееся меню, в котором хранятся параметры конфигурации созданных им команд. Все, что ему нужно было сделать, – это добавить параметр в раскрывающемся меню, чтобы пользователь мог скрыть рейтинг для игрока. Он добавил этот параметр, но всякий раз, когда новый пункт был уже выбран, на странице возникало сообщение: «Вы должны выбрать пункт из списка». И то, что казалось простой манипуляцией, отняло у него часы.
Когда он занимался отладкой кода страницы валидатора, то увидел, что тот читает параметры из кэшированной копии таблицы базы данных. Поэтому он добавил вызов обновления кэша, когда пользователь нажимает кнопку ОК, и теперь этот пункт проверялся, что потребовало от него перейти в другое место кода и внести еще три изменения. Кроме того, еще три страницы обращались к той же странице настроек. Поэтому их тоже понадобилось исправить.
В результате Джастину пришлось сделать более десятка различных изменений в коде, но в итоге он заработал, хотя и благодаря отвратительному читерскому клуджу[56]. Он попросил совета у Даниэль, и она придумала обходной путь решения неприятной проблемы. «Это обновление кэша использует только ID-номер пользователя. Попробуй создать фейк-класс пользователя, который имеет только его идентификатор, а возвращает ноль для всего остального». Это было некрасиво, но сработало.
Наконец Джастин добавил пункт в раскрывающийся список. И ощутил давно знакомое чувство, вызванное пребыванием в офисе допоздна. Он сказал Даниэль:
– Наконец-то дело сделано. Ухожу домой. Я уже весь издерган изменениями, которые пришлось внести ради этой дурацкой настройки. Думаю, я теперь понимаю, что чувствует пинбольный шарик во время игры.
Она ответила:
– Я знаю, что ты имеешь в виду. Казалось бы, нужно просто поменять кое-что на странице авторизации, но это привело к необходимости править код в трех других местах. Два изменения потребовали дополнительных изменений в других классах, а один из этих классов вызывает сервис, выдающий непонятный ответ. И я не знаю, что с этим делать.
Джастин спросил:
– Почему всегда так происходит?
Даниэль ответила:
– Такова сущность программирования. Фактически вопрос заключается в том, действительно ли ты уверен, что только что написанный код работает?
Ей не хотелось задавать этот вопрос. Несколько секунд они пристально смотрели друг на друга и чувствовали себя неуютно.
– Я лучше потрачу еще несколько минут на тестирование этого, – сказал Джастин. Он надел наушники и начал печатать для своей подруги еще одно послание с извинением.
Код и архитектура
В ходе работ над проектом Chrysler Comprehensive Compensation (C3)[57] Кенту Беку было необходимо изменить корпоративную культуру команды, переключив ее с создания «умного» кода на простые решения, а это весьма сложная задача. Один из методов, который он использовал, – это церемония давления со стороны коллег. Например, группа торжественно шествовала к человеку, придумавшему самое заумное решение, ему надевали на голову шапочку с пропеллером, а затем раскручивали его и комментировали эту заумь. Негативное внимание со стороны команды заставило людей отойти от усложненных решений и перейти к простой архитектуре и простым решениям. Но все люди разные, и не все в команде с готовностью приняли ХР. Одному человеку не понравился новый стиль работы и тесное сотрудничество, поэтому он покинул проект.
Алистер Коберн. Быстрая разработка программного обеспечения
XP-команды создают код, который легко изменить. Но как они это делают? Ведь никто не собирается создавать код, который изменить трудно.
Многие разработчики – даже очень умные! – стремятся делать наоборот. Они будут настраивать свои команды на создание кода, пригодного для повторного использования, и потратят много времени, пытаясь спроектировать компоненты, которые можно применять многократно. Но планировать повторное использование очень трудно, и совсем непросто довести до конца разработку чрезмерно абстрактного и обобщенного кода. Ведь объем работы, который придется выполнить для создания общей структуры, ровно такой же, какой необходим для выполнения проекта под ключ. Архитектура для многократно используемой библиотеки, созданная сегодня, вскоре превращается в препятствие, которое команда должна обойти или боится трогать.
Многие люди считают, что хрупкий, трудно изменяемый код – это ошибка, типичная для новичков. Но нередко даже лучшие разработчики создают код, который непросто модифицировать. (Неопытные программисты редко создают достаточно большой исходный код, чтобы в нем проявились такие проблемы.) И необязательно написанное ими программное обеспечение будет плохим или неудачно спроектированным. В большинстве случаев это сводится к вопросу, какой код написан: «заумный» или простой.
Для разработчиков (особенно для умных) вполне естественно пытаться решить не только сегодняшние, но и завтрашние проблемы. Большинство из нас присутствовали на сессиях по планированию, которые казались нескончаемыми, потому что каждый думал лишь о своих проблемах и о том, как их решить. И чем крупнее проблема, которая возникла перед командой, тем больше усилий она требует.
Scrum-команды избегают трудностей, связанных с бесконечным планированием, разбивая проект на спринты. Они сосредоточены на сегодняшних задачах и оставляют все остальное на потом, принимая решение о планировании в последний ответственный момент. И когда XP-команды занимаются итерационным планированием, используя квартальные и недельные циклы, они действуют таким же образом.
Принятие решений в последний ответственный момент – это инструмент не только планирования. Он ценен также при проектировании и кодировании. И это главное средство, при помощи которого XP-команды реализуют принцип простоты.
Если вы работали программистом в нескольких командах, то наверняка видели код, который трудно изменить. Создавался он вовсе не с этой целью, а для того, чтобы выполнять что-то полезное. А потом его стали приспосабливать к другим задачам. И после нескольких циклов перепрофилирования код стал сложным. Так как же это произошло?
Простота начинается с понимания того, как не делать слишком много.
Вот пример, как сложность (отсутствие простоты) может повлиять на продукт. Когда один из авторов этой книги учился в колледже, он получил в подарок устройство, сочетавшее в себе функции блендера, миксера и кухонного комбайна. Не все эти функции работали хорошо: он был неплох как блендер, средненький как миксер и совершенно непригодный как кухонный комбайн. Кроме того, в нем проявились проблемы, которые не хочется видеть в подобных приборах. Например, его сменные части было неудобно хранить и практически невозможно отмыть после использования.
Тем не менее он пользовался им десять лет. Но поскольку весь этот сложный набор приспособлений работал не слишком хорошо, приходилось избегать рецептов, для которых требовался кухонный комбайн. Когда же наконец он засунул агрегат на дальнюю полку (потому что рука не поднималась выкинуть «весьма неплохой» электроприбор) и купил самый дешевый кухонный комбайн, он обнаружил, что теперь может готовить по рецептам, которые раньше были недоступны. Оставалось только удивляться, чего он ждал целых десять лет.
Этот прибор был более чем бесполезен. Вместо помощи в приготовлении пищи по разнообразным рецептам, для чего он и был нужен, комбайн только мешал этому. Но его наличие препятствовало покупке нового устройства, поэтому в течение многих лет хозяин избегал рецептов, связанных с использованием кухонного комбайна. И не потому, что у него не было возможности приготовить эти блюда. Просто с прибором было связано слишком много дополнительных проблем. Но долгие годы ему не приходило в голову купить замену, потому что старый был «весьма неплох».
Причина того, что этот прибор был неудобным, заключалась в его сложности. Чтобы соединить в одном приборе три, нужны технические компромиссы, которые привели к тому, что его было сложно использовать (например, было сложно использовать миксерную насадку, потому что она не хотела работать, если не была идеально закреплена). Замена сложного прибора на три простых – дешевые блендер, миксер и кухонный комбайн – сэкономит деньги, они займут меньше места и позволят готовить больше блюд.
Проблемы, подобные этой, объясняют, почему простота – это одна из ценностей ХР, о чем говорилось в главе 6. ХР-команды признают, что такая проблема, как сложность, может повлиять на планирование проектов. В этой книге мы уже упоминали, как scrum-команды сталкивались со схожими трудностями.
Например, несложно убедить сотрудников, что для команды, стремящейся быть продуктивной и выполнить проект, не имеет смысла держать людей, сидящих сложа руки. Однако некоторые менеджеры, исповедующие командно-административный стиль руководства, доводят эту идею до крайности: они приносят план проекта, где все 100 % ресурсов уже распределены[58], и требуют от разработчиков отчета за каждую минуту работы. Постоянный контроль за 100 %-ной загрузкой персонала запланированной работой перегружает управление проектом. Люди должны следить за использованием своего времени и вносить данные в систему контроля (что несложно сделать в теории, но на практике отнимает уйму времени и сил). Менеджерам необходимо составлять, обновлять и пересматривать планы, и невозможно избежать множества совещаний по «решению» проблем, потому что только кажется, что разработчик занимается делом 95 % своего времени.
Получается сложная система управления проектом, но дополнительное усложнение не добавляет ценности в проект. Теперь команда тратит около 20 % своего времени на отслеживание и разговоры о том, на что уходят остальные 80 %, а это увеличивает длительность проекта. Похоже, команда тратит все больше времени на планерки, обсуждая такие вопросы, как «На сколько процентов завершено дело?» и «Можете ли вы оценить, сколько минут потратите на эту задачу?».
XP-команды, так же как scrum-команды, используют итерации для принятия решений по планированию проекта в последний ответственный момент. Такой способ планирования проектов гораздо проще. XP-команды, как правило, не следят постоянно за временем каждого сотрудника, как показано в нашем примере, потому что мониторинг не помогает выполнять проект. Несмотря на благие намерения, собранная информация редко используется для прогнозирования проекта и почти никогда не пересматривается после его завершения. Как уже было сказано, ситуацию ухудшает то, что проекты со временем меняются. Планирование 100 %-ного распределения ресурсов потребует от команды принятия всех решений в начале проекта. Если какое-то из них оказывается неверным (а это обязательно случится, таков нормальный ход проекта), то вся команда должна будет пересмотреть планы, задачи и варианты распределения.
В этом примере есть более значимый урок, помогающий понять ХР. Он связан с признанием паттернов и их применением для улучшения работы.
Если вам доводилось работать в команде, где строгий руководитель командно-административного типа требует от каждого 100 %-ного распределения и собирает бесконечные совещания, чтобы в этом убедиться, требует от каждого постоянно обновлять свой список задач в соответствии с этим надуманным распределением, то, прочитав несколько последних абзацев, вы, возможно, вспомнили эту атмосферу нескончаемых совещаний. Наверняка вы сразу распознали антипаттерн – модель поведения, которую команда демонстрирует в качестве причины, вызывающей проблемы проекта. Опознание антипаттерна в управлении проектом дает возможность обозначить проблему и надежду на отыскание решения, которое поможет упростить эту работу, что позволит команде вернуться к созданию продукта.
Код тоже может содержать антипаттерны, и его распознание – это первый шаг к упрощению вашего кода. Когда антипаттерн относится к структуре кода или архитектуре решения, это называется код «с душком». XP-команды всегда ищут такой код и вырабатывают привычку исправлять его сразу же, как только найдут, не позволяя распространяться на другие модули.
Мы собираемся потратить некоторое время на обсуждение наиболее распространенных вариантов кода «с душком», чтобы вы могли лучше понять образ мышления успешного ХР-разработчика. Этот конкретный список составлен на основании опыта многих разработчиков, обсуждавших проблемы, всплывавшие в их собственных проектах на протяжении ряда лет. Термины «код “с душком”» и «антипаттерн» впервые стали популярны среди разработчиков во второй половине 1990-х годов во многом благодаря сайту WikiWikiWeb (самый первый из Wiki-проектов, созданный автором Аgile-манифеста Уордом Каннингемом). Этот сайт был (а для некоторых остается) одним из самых популярных мест, где разработчики обсуждают проектирование ПО. Чем больше людей собиралось, чтобы поговорить на эту тему, тем чаще они обнаруживали, что существует ряд общих симптомов, с которыми сталкивался каждый из них[59].
Многие разработчики программного обеспечения (и мы в том числе), впервые сталкиваясь с такими проблемами, реагируют почти на интуитивном уровне.
Это весьма странное ощущение, когда вы мучаетесь непонятным разочарованием и обнаруживаете, что его в точности описывает неизвестный вам человек. И в ходе дальнейшего обсуждения важно иметь в виду, что эти проблемы созданы, признаны и могут быть предотвращены или исправлены людьми. Даже если симптомы носят технический характер, причина в человеческом факторе, поэтому решение должно быть как техническим, так и командно ориентированным.
Когда мы проводим тренинги для разработчиков и говорим о коде «с душком», большинство людей соглашается, что это напоминает «стрельбу дробью». Таким термином описывается ситуация, когда вы хотите сделать небольшое изменение в одной части кода, но обнаруживаете, что оно затрагивает несколько других частей, казалось бы, не связанных с первой. Вы пробуете внести эти изменения и видите, что одно из них требует дополнительной правки в местах, связь которых с первой правкой неочевидна. Если исходный код особенно «плохо пахнет», то нередко программист пытается изменить то, что должно быть простым. Он делает десяток или более переходов в коде и в конце концов сдается, потому что уже не в силах отследить нарастающие каскадом изменения.
Рис. 7.1. Успешные XP-разработчики имеют привычку искать и исправлять код «с душком», например очень большие классы или дублированный код. Этим антипаттернам следует придавать структуру отдельных модулей. В этой главе мы будем использовать шестеренки в качестве визуальной метафоры для кода на рисунках
Когда разработчик «закапывается» в код, являющийся причиной «стрельбы дробью», он часто натыкается на код, издающий другой «запашок», – сырой код (незаконченные объекты, что не редкость в объектно ориентированном программировании). Сырой код появляется, когда программист, чтобы использовать один объект (модуль, блок и т. д.), также должен инициализировать другие объекты в заранее определенном порядке. Например, после инициализации некоторой библиотеки разработчик должен установить значения определенных переменных по умолчанию, а также инициализировать другую библиотеку, от которой зависит первая. Об этом можно узнать только из документации или примеров кода, но неправильная инициализация приведет к сбою или непредсказуемому поведению.
Рис. 7.2. Некоторые примеры кода «с душком» возникают как следствие громоздкой архитектуры системы и сложного взаимодействия модулей
Некоторые примеры кода «с душком» появляются тем же способом, что и нормальный код. Когда ваш код включает очень большие классы (или, в случае не объектно ориентированного кода, – громоздкие процедуры, функции, модули и т. д.), его трудно читать и поддерживать. Но часто это признак того, что код пытается выполнять слишком много задач и может быть разделен на более мелкие модули, которые легче понять. В то же время дублируемый код идентичен (или почти идентичен) блоку программы, который встречается в нескольких местах. Это весьма вероятный источник ошибок, особенно если программист вносит изменения в три копии, но забыл про четвертую.
Другой пример кода «с душком» – это неправильная организация взаимодействия отдельных модулей друг с другом. Спагетти-код, или код со сложной и запутанной структурой, – один из самых старых типов кода «с душком», он известен по крайней мере с 1960-х годов. Часто спагетти-код можно распознать по пугающим комментариям других разработчиков, которые ранее безрезультатно пытались распутать его. А другая разновидность – лазанья-код – может оказаться более коварной проблемой. Современная архитектура программного обеспечения, как правило, делит код на слои. Каждый из них имеет определенную цель или выполняет определенную роль, и эти слои составляют общую архитектуру. Однако когда слоев слишком много и шаблоны, по которым их писали, оказались несогласованными, становится трудно понять, что должен делать каждый слой. Эта ситуация может усугубляться протечками между слоями, где код, типы данных или идеи, которые должны находиться в одном слое, просачиваются в соседние.
Приведенные примеры кода «с душком» обусловлены его структурой. Но бывают также проблемы, связанные с тем, что делает код, то есть с его функциональностью. И успешные ХР-разработчики понимают, что они должны заботиться о поведении кода не меньше, чем о его структуре.
Приведем пример. Команда будет прогнозировать способ использования модуля кода (например, класса Java) в будущем и добавит некий хук, или заполнитель, который впоследствии будет заменен кодом. Хук кажется «бесплатным», но на самом деле имеет цену: он связывает команду принятым сегодня решением, которое можно было бы отложить на будущее. Когда наконец приходит время для использования хука, команда глубже понимает проблему и он должен быть другим. Команда приходит в замешательство, обнаружив, что ее предположения о том, как будет использован хук, привели к необходимости создать еще одну часть кода, которая будет обходить этот хук. Поэтому его стало гораздо труднее изменить (несмотря на то, что он пуст!) – ведь он уже используется в другом месте кода. Программист, привыкший добавлять слишком много хуков, забывает, где они расположены. Он будет постоянно сталкиваться с неприятностями при попытке использовать код, написанный несколько недель назад. Ведь окажется, что нужный код так и не был написан, а вместо него стоит комментарий со словами «надо сделать».
Это антипаттерн: добавление такого количества хуков, что становится трудно точно отследить, что именно делает код.
Другой антипаттерн, создающий сложности в понимании кода, – это зацикленность на исключениях. Исключение – редко встречающаяся ситуация, происходящая при определенном наборе обстоятельств[60]. Например, программа, которая загружает данные из файла, должна обработать случай, когда файл не найден. Ей может также понадобиться отреагировать на ситуацию, когда не удается найти папку, содержащую файл, вероятно, реагируя иначе, чем в первом случае. Возможно также, что файл существует, но не может быть прочитан или его удаляют во время чтения либо данные в нем имеют неверную кодировку. Хороший программист придумает еще множество возможных проблем в такой простой ситуации, как чтение данных из файла. Ну и на чем ему остановиться?
Многие вязнут в обработке слишком большого числа исключений. Но она действительно необходима, и многие ситуации требуют обработки нескольких различных вариантов. Но чем больше обрабатывается вариантов исключений, тем меньше польза для проекта от добавления еще одного. Некоторые программисты попадают в замкнутый круг, пытаясь написать «непрошибаемый» код и тратя на обработку исключений столько же усилий, сколько и на основную часть кода. В этот момент исключения становятся сходными с избыточным планированием и начинают отвлекать усилия от основной работы. Код для обработки ошибок срабатывает редко. Если программа выглядит как запутанный клубок исключений, то ее труднее понять и изменить.
Хорошие разработчики, как правило, относятся к тому типу людей, которые зацикливаются на деталях, и исключения – это как раз такая деталь. Именно глубокий ум может превратить программиста в человека, одержимого исключениями. Когда такое случается, на командных совещаниях начинается бесконечное обсуждение исключений для особых ситуаций, в ходе которого каждый участник неожиданно приобретает твердое убеждение, что значимое для него исключение обязательно должно быть обработано.
Если разработчики чрезмерно увлечены планированием исключений или добавляют слишком много хуков, это можно считать умничаньем. Вместо создания простого, легко изменяемого кода они размышляют о написании усложненного, чересчур абстрактного кода или занимаются решением завтрашних, а не сегодняшних задач.
Это подводит нас к так называемой платформенной ловушке – антипаттерну, вытекающему из умствования разработчиков. Платформенная ловушка – это ситуация, когда разработчику нужно решить некую проблему или выполнить задание. Но вместо того чтобы написать код для решения именно этой задачи, он создает более обширную платформу, которая может быть использована в дальнейшем для работы в схожих ситуациях.
Рис. 7.3. Блестящий веб-комикс xkcd показывает, что происходит, когда разработчики попадают в платформенную ловушку
Рон Джеффрис, партнер Кента Бека по созданию ХР, описал, как избежать платформенной ловушки. «Реализуйте то, в чем вы действительно нуждаетесь в данный момент, и не стремитесь предугадывать, что вам может понадобиться в будущем»[61]. Некоторые XP-команды любят использовать аббревиатуру YAGNI (You Ain’t Gonna Need It – «вам это не понадобится»), если речь заходит о таких ситуациях. Пытаясь предугадать будущие потребности и создавая дополнительный код, чтобы их удовлетворить, вы легко попадаете в платформенную ловушку.
Вместо того чтобы сосредоточиться на текущей задаче, чересчур умные разработчики замахиваются на более глобальные цели. Они размышляют примерно так: «Я могу написать это простое решение, но гораздо лучше сделать код, автоматизирующий такую работу, чтобы никому больше не пришлось ею заниматься». У программиста, начавшего писать веб-страницу, в результате получается конструктор для их создания. Попытка решить конкретную проблему производительности приводит к появлению большого кэша общего назначения. Простая программа для загрузки файлов по расписанию непонятным образом приобретает скриптовый движок.
Нетрудно понять, почему разработчики идут по этому пути. Они думают так: «Если бы кто-то другой создал платформу для работы, которую я сейчас выполняю, то я бы просто ее применил. Так почему бы не потратить немного времени на решение проблемы в общем виде?» Это очень благородно со стороны разработчиков и объясняет, почему так много команд попадают в платформенную ловушку.
Все нормально, и, конечно, в XP нет ничего, что исключает использование или разработку таких платформ. Одна из наших наиболее популярных книг Head First CM учит программистов использовать. NET Framework, технологию Microsoft, для создания Windows-приложений. Существуют отличные готовые платформы для разработки веб-приложений, рендеринга 3D-графики, создания сетевых сервисов и т. д.
Это не значит, что у вашего проекта должна быть установка на создание сетевого сервиса.
Поговорим еще немного о возможности повторного использования, потому что платформенная ловушка – это наше название для антипаттерна, связанного с созданием повторно используемого кода, чего XP-команды учатся избегать. Многократно используемый код (код, который носит достаточно общий характер и может применяться в разных частях системы) – это цель многих разработчиков. И в этом есть определенный смысл. Кнопки в диалоговых окнах в текстовом процессоре похожи друг на друга и работают примерно одинаково. Было бы странно, если бы команда, создающая текстовый редактор, писала отдельный код для каждой кнопки. Программисты напишут код кнопки один раз и будут повторно использовать его по мере необходимости. Но кнопки в диалоговых окнах текстового редактора работают и выглядят так же, как в браузере и других приложениях. Так что код для этих кнопок (вероятно) находится за пределами любой из этих программ – ваша операционная система предоставляет библиотеку для основных кнопок. Код кнопки был написан однажды и повторно используется тысячи раз. Это явно экономит время.
Программисты редко создают что-либо с нуля. В их распоряжении библиотеки, применяемые для чтения и записи файлов, доступа к сетевым ресурсам, графике и т. д. Это основной факт программирования: хороший разработчик, сталкиваясь с незнакомой проблемой, прежде всего ищет решение в веб-библиотеке. Поэтому, решив проблему, с которой могут столкнуться другие, он часто старается поделиться вариантом кода[62]. Это продуктивный способ создавать программное обеспечение.
Вы знаете, что можете использовать библиотеку как независимую часть своего проекта.
Разница в том, что в библиотеке хранится код, разделенный на небольшие компоненты, которые можно применять повторно. Если цель заключается в создании простого кода, то каждый компонент должен делать только одну функцию. Компонент, выполняющий несколько функций, следует разделить на меньшие, более независимые модули. Это так называемое разделение ответственности; эффективные ХР-разработчики признают, что это важный элемент обеспечения простоты кода.
А платформа – это объединение множества мелких, повторно используемых частей в одну большую систему. Изучение языка C#, например, помимо его синтаксиса означает также освоение. NET Framework.
Эта платформа включает в себя библиотеки для доступа к файлам, выполнения математических расчетов, подключения к сетям и многого другого (в том числе использования кнопок). Когда вы начинаете создавать свою программу при помощи C# и. NET, вы бесплатно получаете все упомянутые выше модули, потому что они часть платформы. NET. Из нее невозможно выделить нужный кусочек кода. И действительно, не имеет смысла пытаться использовать одну часть платформы. NET в программе, которая написана без ее использования. Как и в большинстве платформ, в ней многие части были объединены в большую единую систему.
Платформы гораздо сложнее библиотек. Команда, пытающаяся создать платформу, когда для данной задачи больше подходит библиотека, вынуждена использовать чрезмерно усложненную архитектуру. Часто эта ошибка встречается из-за того, что программисты видят, как другие платформы сберегают им массу времени, и хотят, чтобы их код делал то же самое.
Недостаток такого подхода в том, что, желая получить все эти компоненты даром, вы должны использовать платформу целиком. Иногда это заставляет вас взглянуть на проблему по-новому. Разработчик. NET действительно будет воспринимать проблему иначе, чем Java-разработчик (разница не всегда велика, потому что у этих платформ много общих концепций), и абсолютно по-другому, чем программист на С++, Python, Perl или Lisp. Так происходит, потому что, когда у вас есть набор инструментов для устранения проблем, вы ищете решение, отталкиваясь от этих инструментов. Это только примеры языков и платформ (думая о разработке ПО на Java, Python или Perl, вы наверняка будете учитывать имеющиеся в этих языках стандартные библиотеки), поэтому в них не принимаются во внимание различные ограничения, с которыми вы столкнетесь, решая свои проблемы.
Рис. 7.4. Создание сложных платформ для решения простых задач иногда воспринимается как дело, которым надо заниматься именно сейчас (источник: xkcd)
Рис. 7.5. Платформа, которая сегодня кажется отличным решением, завтра может превратиться в обузу
Приведем типичный пример мышления, ориентированного на платформы. Команды используют скрипты для автоматической сборки программного обеспечения. (В главе 6 мы узнали, что в XP-командах эти скрипты выполняются менее чем за 10 минут.) Для создания скриптов существует немало инструментов, и многие из них включают в себя скриптовые языки. Но для разработчика с платформенным мышлением, работающего над несколькими проектами, недостаточно просто написать отдельный скрипт для каждого проекта. Похоже, в этих скриптах дублируется слишком много кода (часто так оно и есть), поэтому такой программист напишет единую сборочную платформу для всех проектов. («Если вы используете мою платформу, то вам не придется писать сборочный скрипт. Вы получите его готовым!) Поэтому вместо недлинных скриптов для каждого проекта создается большая платформа, которая требует отдельной поддержки. Этот разработчик пошел на сделку: он предотвратил повтор нескольких десятков строк сборочного скрипта, заменив их на платформу, которая содержит сотни, даже тысячи строк кода. Когда во время сборки что-то пойдет не так (по закону Мерфи это происходит в ночь перед выпуском), вместо устранения небольшой неполадки в сборочном скрипте разработчику придется искать ошибку в большой платформе. Это нельзя назвать простым решением.
Объединение значительного числа функций в большой платформе для решения определенной проблемы может действительно дать результат. Но если проблема меняется, то внести изменения в платформу труднее.
Иными словами, объединяя множество разных частей в большие платформы, члены команды думают, что экономят время, но на самом деле они лишь ограничивают способность реагировать на новые запросы. Мы называем это явление платформенной ловушкой и можем использовать как пример для изучения простоты и ее влияния на проект. Причина, по которой нам нравится приводить в качестве примера такую ловушку, заключается в том, что она отражает важный аспект мышления, который не всегда совместим с XP: некоторые разработчики предпочитают объединять все функции в один большой блок, а не разделять их на множество мелких модулей.
Мы только что описали несколько разновидностей кодов «с душком», которых ХР-команды обычно стараются избегать. Все эти коды объединяет одна черта: они увеличивают сложность проектов. Верно и обратное: если вы обнаружили, что вам необходимо запоминать, как инициализировать объект, или трудно удерживать в голове каскад вынужденных изменений, или вы подолгу пытаетесь разобраться в спагетти-коде, значит, исходный код вашего проекта излишне усложнен. Именно поэтому XP-команды стремятся как можно раньше найти и исправить код «с душком».
Речь идет не только о коде «с душком», который, возможно, не такой уж частый гость в ваших проектах. Тем не менее мы выбрали этот пример, потому что за долгие годы общения с разработчиками обнаружили, что почти все сталкиваются с похожими проблемами в своем коде. Они возникают неслучайно и не из-за низкой квалификации разработчиков или их лени. Это является результатом плохих привычек программистов, особенно когда они попадают в ситуацию цейтнота или вынуждены обходить ограничения (в том числе те, что заложили в код в начале проекта).
Так что же вы делаете, когда в вашем проекте появляется код «с душком»? Можно ли это предотвратить?
Ключевые моментыХР-команды выявляют код «с душком» (или антипаттерны), чтобы избежать сложности и сохранить простоту архитектуры.
Код «с душком», такой как сырой код и очень большие классы, помогает командам обнаружить отдельные модули, которые можно упростить.
Такой код «с душком», как лазанья-код, помогает им искать проблемы в более крупных конструкциях.
Особенно неприятно, когда код «с душком» вызывает эффект «стрельбы дробью», то есть разработчик пытается исправить проблему, но обнаруживает, что внесенные изменения требуют целой цепочки правок в других частях кода.
Команды, чрезмерно увлекающиеся планированием в стремлении предусмотреть все особые случаи, добавляют слишком много хуков или создают большие платформы для решения отдельных проблем, что приводит к усложнению кода.
Даже высококвалифицированные специалисты, подверженные плохим привычкам, могут столкнуться с этими проблемами.
Принимать решения по коду и проекту в последний ответственный момент
Переход к проектированию в XP-стиле – это смещение дат принятия проектных решений. Проектирование откладывается до тех пор, пока не появится возможность использовать накопленный опыт и сразу же внедрять принятые решения. Это дает возможность команде:
• разворачивать программное обеспечение как можно раньше;
• принимать решения с уверенностью;
• избегать последствий плохих решений;