Методологии разработки программного обеспечения
Часть 2. Экстремальное программирование
Ускоренная и совместная разработка приложений
Экстремальное программирование
Принципы XP и используемые методы ускорения разработки
аверное, каждый проектировщик или аналитик хотя бы раз в жизни сталкивался с заказчиком, стремящимся получить свой проект как можно дешевле и вдобавок в максимально сжатые сроки. Но если стоимость проекта — вполне реальный предмет торга, то вести переговоры о корректировке сроков сдачи проекта куда сложнее. Нетерпеливых клиентов сегодня становится все больше и больше, что объясняется и состоянием современного динамичного рынка, и падающим уровнем доверия между исполнителями и заказчиками, и поведением инвесторов, у которых аппетит приходит во время еды (при наличии более или менее работающей версии продукта деньги на дальнейшую разработку дают намного охотнее), и т.д. В связи с этим классические методологии разработки (при которых долгий цикл собственно проектирования и сбора информации, когда клиент вкладывает значительные средства, а реального результата довольно долго не получает) вступают в весьма жесткое противоречие с интересами нетерпеливого заказчика. Все это и дало толчок развитию альтернативных методологий проектирования в двух основных направлениях: повышение доверия заказчика путем предоставления реальных доказательств успешно развивающегося процесса разработки и резкое сокращение сроков разработки продукта. Группа таких методологий получила название «активное программирование».
Ускоренная и совместная разработка приложений
ак правило, конечные пользователи и представители руководства компании-заказчика полагают, что процесс проектирования не увенчался успехом, если отсутствуют реальные готовые компоненты. Зачастую заказчик настаивает на досрочном проведении этапа реализации проекта, чтобы как можно быстрее получить конкретный результат и продемонстрировать его. В таком случае существует большой соблазн выбрать ускоренную разработку приложений (УРП) или совместную разработку приложений (СРП). Подобные методы предусматривают разработку рабочего прототипа с последующей демонстрацией его пользователям, которые отмечают, что им нравится, а что нет. После этого проектировщик дорабатывает прототип с учетом сделанных замечаний, а затем снова демонстрирует то, что получилось. Процесс повторяется до тех пор, пока пользователи не будут удовлетворены тем, что они видят, а прототип не станет рабочим приложением. Обычно устанавливаются лимит времени и количество итераций, ибо в противном случае пользователи будут бесконечно требовать новых совершенствований прототипа. Теоретически это позволяет получить именно ту систему, которая необходима пользователям.
Итак, здесь мы наблюдаем итеративную модель разработки с очень короткими циклами спирали в обоих случаях. И в том и в другом методе сокращено время, затрачиваемое на начальные этапы проектирования: стратегию (либо опускается вообще, либо сливается с анализом), анализ (в большинстве случаев ограничивается первичной выборкой информации и анализом форм — как правило, отчетов, по которым и пытаются восстановить структуру функций системы), проектирование (нацелено на как можно более быстрое получение первичного прототипа). Результатом разработки является прототип, который затем подлежит промышленной реализации. В данном случае тестирование производится при активном участии заказчика, либо заказчик становится тестером (в лучшем случае бета-тестером).
На практике подобный подход к разработке приложений сопряжен с проблемами, перечисленными ниже:
• Все внимание сконцентрировано на экранных формах, а все, что касается правил обработки данных и системных функций, остается за кадром. Существует искушение начать работу с отчетов, в то время как отчет является не стартовым, а производным продуктом информационной системы.
• Пользователи полагают, что если вариант прототипа согласован, то модуль готов. На самом деле это может быть всего лишь картинка с набором «заглушек» для вызовов системных функций и взаимодействия с другими модулями.
• Модули проектируются изолированно друг от друга. Следствием этого являются противоречия модулей, дублирование функций и данных, что может быть выявлено только при тестировании комплекса модулей.
• Функциональные возможности наращиваются параллельно в нескольких направлениях, поэтому структура хранилища данных должна контролироваться. При УРП схема базы данных напоминает свалку, где таблицы лепятся на скорую руку, а результат — набор противоречивых и дублирующихся данных.
• Документация при использовании метода УРП, как правило, отсутствует по двум причинам: не хватает времени и создается иллюзия, что пользователь способен без документов поняв суть происходящего. Когда же приложение начинает работать не так, как ожидал пользователь, возникают проблемы.
• Способы обработки исключительных ситуаций оказываются различными для разных модулей.
• Возникает проблема интеграции модулей: целостной системы, как правило, не получается, потому что изначально она проектировалась как набор компонентов, которые впоследствии были наспех связаны между собой.
• Контроль качества продукта вступает в жесткое противоречие со сроками разработки проекта, в результате чего стадии тестирования и внедрения очередной версии продукта практически сливаются и переносятся непосредственно на полигон заказчика. Понятно, что в этом случае происходит с заказчиком, который крайне недоволен качеством продукта; иными словами, сор из избы выносится абсолютно не вовремя.
Возникает вопрос: можно ли решить подобные проблемы и каким образом? Ведь так хочется получить проект максимально быстро! В какой-то мере экстремальное программирование (eXtreme Programming, XP) можно считать эволюцией, а возможно, и революцией в сфере более молодых методологий активного программирования. Подойдет ли данная методология конкретно для вашего коллектива разработчиков — решать вам и только вам, поскольку, например, далеко не все приходят в восторг от экстремальных видов спорта.
Экстремальное программирование
Принципы XP и используемые методы ускорения разработки
Отцом-идеологом экстремального программирования считают Кента Бека (Kent Beck). XP является достаточно молодой методологией, оценки которой весьма противоречивы — от восторженных до резко негативных. Основными принципами являются:
• Простота решений (simplicity).
• Интенсивная разработка малыми группами (не больше 10 человек), активное общение в группе и между группами (communication).
• Обратная связь с клиентом (feedback), который фактически вовлечен в процесс разработки.
• Достаточная степень смелости (courage) и желание идти на риск.
Первый фактор ускорения разработки — итеративность: разработка ведется короткими итерациями при наличии активной взаимосвязи с заказчиком. XP — это итеративный процесс разработки, который сам по себе не является революционным. Итерации как таковые предлагается делать короткими, рекомендуемая длительность — 2-3 недели и не более 1 месяца. За одну итерацию группа программистов обязана реализовать несколько свойств системы, каждое из которых описывается в пользовательской истории (user story). Пользовательские истории в данном случае являются начальной информацией, на основании которой создается модуль. Пользовательские истории отличаются от прецедентов (use case): пользовательская история коротка — 1-2 абзаца, тогда как прецеденты обычно пишут достаточно подробными, с основным и альтернативными потоками — таким образом, получается примерно страница плюс схема (наиболее распространенная формализация в настоящее время предложена в UML); истории пользователей пишутся самими пользователями (которые в XP являются частью команды) в отличие от прецедентов, которые обычно пишет системный аналитик. Отсутствие формализации описания входных данных проекта в XP стремятся компенсировать посредством активного включения в процесс разработки заказчика как полноправного члена команды и за счет наличия постоянного контакта с заказчиком (активное общение и непрерывная поддержка обратной связи). В данном случае extreme — это степень привлечения заказчика к программистской кухне, что обусловлено стремлением сжать сроки разработки за счет коммуникации и обратной связи.
Второй фактор ускорения разработки продукта — наличие малых групп и парное программирование (когда два программиста вместе создают код на одном общем рабочем месте). Все это нацелено на достижение высокого уровня общения в группе, а также на как можно более раннее обнаружение проблем (как ошибок, так и срыва сроков). Парное программирование преследует цель стабилизации проекта, так как при данной методологии высок риск потери кода по причине ухода программиста, не выдержавшего интенсивного графика работы. В этом случае второй программист из пары играет роль «наследника» кода (что в классических методиках реализуется в технической документации). Немаловажно и то, как именно распределены группы в рабочем пространстве — в XP используется открытое рабочее пространство, которое предполагает быстрый и свободный доступ всех ко всем; как правило, рабочее пространство строится на основе круга.
Третий фактор ускорения разработки процесса — принятие первого наипростейшего рабочего решения. В данном случае экстремальность метода связана с высокой степенью риска решения, обусловленного поверхностностью анализа и жестким временным графиком. Реализуется минимальный набор главных функций системы на первой и каждой последующей итерации; функциональность расширяется на каждой итерации.
Практики
Обычно XP характеризуют набором из 12 действий (практик), которые необходимо выполнять для достижения хорошего результата. Практики XP не определяют сам процесс XP, но XP определяет эти практики — то есть выполнение практик не гарантирует результата. Ни одна из практик не является принципиально новой, но в XP они собраны вместе.
• Планирование процесса (planning game). Вся команда собирается вместе, принимается коллективное решение о том, какие свойства системы будут реализованы в ближайшей итерации. Набор свойств определяется пользовательскими историями. XP-трудоемкость каждого свойства определяется самими программистами.
• Тесное взаимодействие с заказчиком (feed-back, on-site customer). Заказчик должен быть членом XP-команды (on-site customer). Он пишет пользовательские истории, выбирает истории, которые будут реализованы в конкретной итерации, и отвечает на вопросы, касающиеся бизнеса. Заказчик должен быть экспертом в автоматизируемой предметной области. Необходимо постоянное наличие обратной связи с заказчиком (feed-back).
• Метафора системы (system metaphor). Хорошая метафора системы означает простоту именования классов и переменных. В реальной жизни поиск метафоры — крайне сложное занятие; найти хорошую метафору непросто. В любом случае команда должна иметь единые правила именования.
• Простая архитектура (simple design). Любое свойство системы должно быть реализовано как можно проще. Программисты в XP-команде работают под девизом: «Ничего лишнего!». Принимается первое наипростейшее работающее решение, реализуется необходимый уровень функциональности на данный момент. Тем самым экономится время программиста.
• Стандарты кодирования (coding conventions). Стандарты кодирования нужны для обеспечения других практик: коллективного владения кодом, парного программирования и рефакторинга. Без единого стандарта выполнять эти практики как минимум сложнее, а в реальности вообще невозможно: группа будет работать в режиме постоянной нехватки времени. Детальные стандарты не требуются, необходимо стандартизировать только важные вещи. Определение наиболее важных объектов стандартизации в XP субъективно.
• Рефакторинг (refactoring). Рефакторинг — это оптимизация существующего кода в сторону упрощения, что предусматривает постоянную работу по упрощению кода. Сохраняя код прозрачным и определяя его элементы всего один раз, программисты сокращают число ошибок, которые впоследствии придется устранять. При реализации каждого нового свойства системы программист должен подумать над тем, можно ли упростить существующий код и как это поможет реализовать новое свойство. Кроме того, нельзя совмещать рефакторинг с дизайном: если создается новый код, рефакторинг надо отложить.
• Парное программирование (pair programming) — одна из самых известных XP-практик. Все программисты должны работать в парах: один пишет код, другой смотрит. Таким образом, необходимо размещать группу программистов в одном месте, что легче всего сделать на территории заказчика (все необходимые члены команды географически находятся в одном месте); XP наиболее успешно работает в нераспределенных коллективах программистов и пользователей.
• 40-часовая рабочая неделя. Программист не должен работать более 8 часов в день. Необходимость сверхурочной работы (overtime) — это четкий индикатор проблемы на данном конкретном направлении разработки; к тому же заказчик не платит за сверхурочную работу в XP. Поиск причин сверхурочной работы и их скорейшее устранение — одно из основных правил.
• Коллективное владение кодом (collective code ownership). Каждый программист в коллективе XP должен иметь доступ к коду любой части системы и вносить изменения в любой код. Обязательное правило: если программист внес изменения и система после этого работает некорректно, то именно этот программист должен исправить ошибки. В противном случае работа системы уподобится тотальному хаосу.
• Частая смена версий (small releases). Минимальная итерация — один день, максимальная — месяц; чем чаще осуществляются релизы, тем больше недостатков системы будет выявлено. Первые релизы помогают выявить недостатки на самых ранних стадиях, далее функциональность системы расширяется (на основании тех же пользовательских историй). Поскольку пользователь включается в процесс разработки начиная с первого релиза, то он оценивает систему и выдает пользовательскую историю плюс feedback. На основании этого определяется следующая итерация: каким будет новый релиз. В XP все направлено на обеспечение непрерывной обратной связи с пользователями.
• Непрерывная интеграция (continuous integration). Интеграция новых частей системы должна происходить как можно чаще, как минимум раз в несколько часов. Основное правило интеграции следующее: интеграцию можно производить, если все тесты проходят успешно. Если тесты не проходят, то программист должен либо внести исправления и тогда интегрировать составные части системы, либо вообще не интегрировать их. Правило это жесткое и однозначное — если в созданной части системы имеется хотя бы одна ошибка, то интеграцию производить нельзя. Частая интеграция позволяет быстрее получить готовую систему, вместо того чтобы тратить на сборку неделю.
• Тестирование (testing). В отличие от большинства остальных методологий тестирование в XP — одно из важнейших составляющих. Экстремальный подход заключается в том, что тесты пишутся до написания кода. Каждый модуль обязан иметь unit test — тест данного модуля; таким образом, в XP осуществляется regression testing (возвратное тестирование, «неухудшение качества» при добавлении функциональности). Большинство ошибок исправляются на стадии кодирования. Тесты пишут сами программисты; любой программист имеет право написать тест для любого модуля. Еще один важный принцип: тест определяет код, а не наоборот (такой подход носит название test-driven development), то есть кусок кода кладется в хранилище тогда и только тогда, когда все тесты прошли успешно, в противном случае данное изменение кода отвергается.
Итак, XP крайне пренебрежительно относится ко всем артефактам процесса разработки, кроме исходного кода. Процесс XP является в высшей степени неформальным, но требует высокого уровня самодисциплины. Если это правило не выполняется, то XP мгновенно превращается в хаотичный и неконтролируемый процесс. XP не требует от программистов написания множества отчетов и построения массы моделей. В XP каждый программист считается квалифицированным работником, который профессионально и с большой ответственностью относится к своим обязанностям. Если в команде этого нет, то внедрять XP абсолютно бессмысленно — лучше для начала заняться перестройкой команды. Риск разработки снижается только в команде, которой XP подходит идеально, во всех остальных случаях XP — это процесс разработки с наиболее высокой степенью риска, поскольку другие методы снижения коммерческих рисков, кроме банального человеческого фактора, в XP просто отсутствуют.
Существующие риски применения методологии
Следует выделить риски XP, способные завалить проект, если не учитывать и не предотвращать их.
• Этап планирования (planning game). Программисты реализуют только те функции, которые необходимы для возможностей, выбранных на данной итерации заказчиком. В результате такого решения за кадром остается развитие системы, вследствие чего при разработке возникает необходимость строить «заглушки» и переписывать код.
• Постоянное участие заказчика (on-site customer). Представитель заказчика в период работы над системой находится в команде разработчиков, причем требования к квалификации этого человека или команды весьма высоки. Если заказчик не согласился предоставить персонал уровня экспертов, то проект попадает в группу наиболее высокого риска.
• Метафора (metaphor). Общий вид системы определяется при помощи метафоры или набора метафор, над которыми совместно работают заказчик и программисты. Если не ведется журнал данного процесса и структура наименований не стандартизована, то такой процесс может оказаться бесконечно итерационным.
• Простая архитектура (simple design). В каждый момент времени разрабатываемая система выполняет все тесты и поддерживает все взаимосвязи, определяемые программистом, не имеет дубликатов кода и содержит минимально возможное количество классов и методов. Это правило кратко можно выразить так: «Каждую мысль формулируй один и только один раз». Данный принцип вступает в противоречие с быстротой написания кода. Без наличия высокой самодисциплины и жестких стандартов кода система немедленно попадает в группу риска.
• Частая смена версий (small releases). Систему запускают в эксплуатацию уже через несколько месяцев после начала реализации, не дожидаясь окончательного разрешения всех поставленных проблем. Периодичность выпуска новых версий может варьироваться от ежедневной до ежемесячной. Протестировать за такой срок более-менее сложный компонент невозможно; заказчик фактически выступает в роли бета-тестера. Системы, к которым предъявляется требование непрерывной надежной работы (так называемое требование 24Ѕ7), входят в группу риска.
• Переработка системы (refactoring). Архитектура системы постоянно эволюционирует. Текущий проект трансформируется, при этом гарантируется правильное выполнение всех тестов. Экстремальное программирование исходит из того, что переделать часть системы всегда можно, причем без особых затрат. Однако практика довольно часто свидетельствует об обратном.
• Непрерывная интеграция (continuous integration). Новый код интегрируется в существующую систему не позднее чем через несколько часов. После этого система вновь собирается в единое целое и прогоняются все тесты. Если хотя бы один из них не выполняется корректно, внесенные изменения отменяются. В данном случае не всегда понятно, кто именно будет исправлять ошибки, причем не только локальные, но и наведенные неправильным кодом. Проведение комплексных тестов на данном этапе не предполагается; кроме того, изменения сохраняются даже в том случае, когда ошибка обнаружена.
• Программирование в паре (pair programming). Весь код проекта пишут группы по два человека, использующих одно рабочее место. Человеческий фактор в данном случае играет определяющую роль: пара или работает или нет, третьего не дано.
• 40-часовая неделя (40-hour weeks). Объем сверхурочных работ не может превышать по длительности одну рабочую неделю. Даже отдельные случаи сверхурочных работ, повторяющиеся слишком часто, служат признаком серьезных проблем, которые требуют безотлагательного решения. Как показывает практика применения экстремального программирования (несмотря на целый ряд положительных примеров, приводимых сторонниками данного метода), сверхурочная работа при таком подходе — это правило, а не исключение, и борьба с проблемами в данном случае — явление постоянное. Усиливается она в период замены текущей сырой версии продукта очередной — менее сырой. Если заказчик не получает постоянных доказательств улучшения системы, значит, у вас возникли серьезные проблемы.
• Коллективное владение (collective ownership). Каждый программист имеет возможность при необходимости в любое время усовершенствовать любую часть кода в системе. Без стандарта контроля исходного кода процесс разработки приобретает абсолютно неконтролируемый характер.
• Открытое рабочее пространство (open workspace). Команда разработчиков располагается в большом помещении, окруженном комнатами меньшей площади. В центре рабочего пространства устанавливаются компьютеры, на которых работают пары программистов (причем в соответствии с вышеизложенными принципами, все это должно располагаться на территории заказчика, поскольку он весьма активно привлекается к процессу разработки). При наличии территориально распределенной группы разработчиков и заказчиков проект требует стандартизации протокола взаимодействия (быстро, надежно, безотказно) или попадает в группу риска.
• Тесты (tests). Программисты постоянно пишут тесты для модулей (unit tests). Собранные вместе, эти тесты должны работать корректно. Для этапов итерации заказчики пишут функциональные тесты (functional tests), от которых также требуется правильная работа. Однако на практике это не всегда достижимо. Чтобы принять верное решение, необходимо понять, во что обойдется сдача системы с заранее известным дефектом, и сравнить это с ценой задержки на его устранение. Тесты, написанные самими программистами (особенно в условиях сверхурочных работ), не являются полнофункциональными и уж тем более не учитывают особенностей многопользовательской работы. На более продвинутые тесты у разработчиков обычно не хватает времени. Решается данная проблема путем привлечения на определенный срок контакторов, что связано с большой ролью человеческого фактора: поскольку техническая документация изначально отсутствует, то информация передается посредством общения программистов. Хотя, конечно, можно построить систему разработки таким образом, что от начала до конца всем будут заниматься одни и те же люди. К сказанному необходимо добавить, что тестирование системы вовсе не исчерпывается тестами компонентов (units); не менее важны тесты взаимодействия между ними, это же относится и к тестам надежности работы. И тем не менее метод экстремального программирования не предусматривает создания тестов данного класса. Это объясняется тем, что сами подобные тесты могут представлять достаточно сложный код (особенно это касается тестов — имитаторов реальной работы системы). В данной технологии также никак не учитывается еще один важный класс тестов — тесты поведения системы при росте объемов обрабатываемой информации. При высокой частоте изменения версий выполнить такой тест технологически невозможно, поскольку его проведение требует стабильного и неизменного кода проекта, например в течение недели. В таком случае придется или приостанавливать разработку компонентов, или создавать на время проведения теста параллельную версию проекта, которая будет сохраняться неизменной, тогда как другая при этом будет изменяться. Затем нужно будет выполнить процесс слияния кода. Но в этом случае тест придется создавать заново, так как методы экстремального программирования просто не предусматривают разработку средств, позволяющих прогнозировать поведение системы при тех или иных изменениях. Решать данные проблемы в XP предлагается посредством все того же человеческого фактора и самодисциплины.
• Не более чем правила (just rules). Члены коллектива, работающего по технологии экстремального программирования, обязуются выполнять изложенные правила. Однако это не более чем правила, и команда может в любой момент изменить их, если ее члены достигнут принципиального соглашения по поводу внесенных изменений. Данный принцип серьезно зависит от человеческого фактора; нарушение дисциплины разработки влечет за собой срывы сроков и в результате ведет к краху проекта.
В итоге мы получаем метод, потенциально обладающий высокой адаптацией к серьезно и часто изменяющимся требованиям к проекту, но в то же время не свободный от ряда принципиальных недостатков и в очень высокой степени зависимый от человеческого фактора.
Таким образом, результат применения метода экстремального программирования может получиться либо экстремально хорошим, либо экстремально плохим.