Книга: Постигая Agile
Назад: Инкрементальная архитектура и целостные XP-практики
Дальше: Глава 8. Lean, ликвидация потерь и целостная картина

Акт V. Окончательный результат

Даниэль и Джастин были заняты парным программированием, когда Даниэль вдруг воскликнула:
– Ты понимаешь, что мы работаем в паре уже почти три месяца?
Прошло около года с тех пор, как Даниэль рассказала команде об XP. Они делали выпуски каждую неделю, но последний недельный цикл был особенным. Компания объявила о рекламной акции в одной из крупнейших телевизионных сетей, и команда просто вытолкнула код в производство. Пару минут Даниэль и Джастин вспоминали, как шла работа на протяжении нескольких последних циклов.
Джастин сказал:
– Ты права. Все это время мы работали парами, но меняли партнеров так часто, что, по-моему, я успел поработать с каждым членом команды.
Даниэль спросила:
– Когда ты в последний раз засиживался допоздна?
Джастин задумался.
– Знаешь, мне придется поискать в телефоне последнее сообщение с извинениями. Давненько это было.
– Думаю, это потому, что мы стали лучше, – сказала Даниэль. – Я знаю, что теперь пишу более простой код, чем шесть месяцев назад.
– Ты права. Когда я впервые прочитал о разработке через тестирование, такая идея показалась мне чересчур абстрактной. Теперь же я вижу в ней смысл, – ответил Джастин. – Раньше мы рассуждали об этом всей командой, пытаясь убедить друг друга, что это пустая трата времени. Я не припомню, когда в последний раз мне нужно было спорить на эту тему.
Даниэль добавила:
– Самое забавное – это отсутствие ощущения, что я стала работать совсем по-другому.
Проходившая мимо Бриджит остановились и прислушалась.
– А я эту разницу чувствую, – сказала она. Джастин и Даниэль удивленно уставились на нее. Они не заметили, как она подошла. – Раньше моя работа в основном заключалась в том, чтобы убедить менеджеров продуктов дать нам больше времени. Мы всегда отставали от графика, и казалось, что любая мелочь требует нескольких месяцев работы.
Джастин спросил:
– А как теперь?
– Совершенно иначе! Раньше мне все время приходилось говорить «нет». А теперь я обычно соглашаюсь, даже если меня просят о действительно крупной задаче. Вы сделали мою работу намного проще.
– Я догадываюсь, почему вы больше не кричите на нас, – сказала Даниэль. – И думаю, именно поэтому мы не вкалываем в выходные, пытаясь наверстать упущенное время.
С минуту Бриджит смотрела на Джастина и Даниэль.
– Постойте, так, значит, вы могли бы работать больше?
Джастин решил, что она пошутила. Даниэль не была уверена в этом.
– Я думаю, нам еще надо подучиться, – сказала она.

 

Ключевые моменты
Разработчики исправляют код «с душком» путем его постоянного рефакторинга или улучшения структуры кода без изменения его поведения.
За счет беспощадного рефакторинга XP-команды избегают технического долга или проблем в коде, которые известны, но еще не были исправлены.
Временной резерв помогает убедиться в том, что в каждом недельном цикле достаточно времени для оптимизации и погашения технической задолженности.
Непрерывная интеграция помогает командам найти проблемы интеграции на ранней стадии, когда их легче исправить.
Когда команда занимается рефакторингом, оплачивает технический долг и исправляет проблемы кода, в итоге она получает код, который легко изменить.
XP-команды используют инкрементальную архитектуру, создавая несвязанный код, который состоит из маленьких независимых модулей.
Команды инкрементально собирают только те модули, которые непосредственно необходимы для решения текущей проблемы, и доверяют друг другу принимать работающие решения в последний ответственный момент.
Энергичная работа позволяет XP-командам создать среду, где каждый сотрудник может программировать в стабильном темпе и располагает достаточным временем, чтобы сделать все правильно.
Члены ХР-команды доверяют друг другу и чувствуют, что они единое целое.
Часто задаваемые вопросы
Инкрементальная архитектура – это звучит слишком абстрактно. Неужели кто-то действительно создает программные продукты таким образом?
Когда люди называют что-то «абстрактным», зачастую это означает: «я еще не пробовал так делать, но, по-моему, будет очень непросто».
В ХР нет ничего абстрактно-теоретического. Каждая практика здесь – это определенный навык, которому программисты должны учиться, практиковаться в нем и совершенствоваться. Чем лучше они усваивают такие практики, тем быстрее превращают их в полезные привычки при написании кода.
Ценности и принципы – это вполне практические идеи, которые помогут улучшить навыки работы каждого в отдельности и команды в целом.
Вот почему при работе с XP нужна практика. Невозможно, купив гитару, ноты и самоучитель, стать за ночь великим музыкантом. Точно так же нельзя, начав применять XP-практики, сразу их полностью освоить.

 

Когда бы я ни добавлял элементы технического долга в качестве временного резерва, они просто не выполняются. Как же мне погасить этот долг?
Если вы обнаруживаете, что ваша команда редко принимается за выполнение тех элементов в недельном цикле, которые были добавлены в качестве временного запаса, значит, вы закладываете в каждый цикл слишком много задач. Элементы временного резерва не относятся к числу необязательных. Они всего лишь не препятствуют команде выпустить готовое ПО в конце итерации. Это важные элементы, и большинство из них должно быть выполнено. Если их не удается сделать, то попробуйте уменьшить общее количество элементов при планировании недельного цикла.
К тому же, если эти элементы технического долга так и не выполняются, то, возможно, у вашей команды есть проблемы с мировоззрением. Действительно, существует ловушка, связанная с техническим долгом, в которую попадают многие команды. Они будут выявлять технический долг, но вместо его безотлагательного погашения добавят эти задачи в бэклог, используя карточки, электронные таблицы, тикеты и другие механизмы отслеживания. Как только техническая задолженность определена, она получает более низкий приоритет, чем развитие новых возможностей. Вряд ли команду, которая никак не соберется погасить технический долг, а просто признает его и помечает как задачу на будущее, можно назвать хорошей.
Команда, не устраняющая технический долг, воспринимает его как естественный побочный продукт разработки. Для нее важнее выпустить новую функцию – даже если это приводит к читерским манипуляциям или клуджам, – чтобы проект мог двигаться дальше.
И действительно, нет ничего предосудительного в том, чтобы считать поставку ценного программного обеспечения более важной, чем создание красивого технического решения. Причина, по которой успешные ХР-команды постоянно устраняют технический долг, заключается в том, что таким образом легче продолжить поставку ценного ПО в будущем.
Если вы считаете нормой устранение технического долга во время добавления дополнительного кода, а также проведение постоянного рефакторинга в ходе работы, то вы чувствуете, что делаете важное дело. Каждый в вашей команде знает, что нужно гасить технический долг, как только он обнаружен, потому что это дает возможность легко изменять исходный код. Вот почему члены XP-команды резервируют в недельном цикле достаточно времени (и действительно чувствуют, что его хватит), чтобы устранять проблемы.
Если вы обнаружите, что технический долг накапливается, то следует обсудить это с командой. Постарайтесь выяснить, не связано ли это с внешним давлением, цель которого – добавить как можно больше новых функций. Или дело в том, что вы не считаете погашение настолько важным, чтобы заняться им немедленно. А может, это происходит потому, что вашу команду поощряют за добавление новых «крутых» функций, а не за пломбирование дыр. Если погашение технического долга требует столько же усилий, сколько создание новых функций, но вы собираетесь продемонстрировать серьезные улучшения и руководство знает, что вы пишете новый «крутой» модуль, от которого пользователи будут в восторге, то есть смысл отодвинуть технический долг на нижние позиции в списке приоритетов. Независимо от причины обсуждайте это друг с другом, чтобы принять верное решение.

 

Некоторые XP-принципы звучат сомнительно. Не потому ли здесь говорится о самоподобии, что это звучит внушительно, или дело в том, что методология создавалась в 1990-е, когда все обсуждали самоподобие, фракталы и теорию хаоса?
Вовсе нет. Легко отказаться от принципа, если вы еще не видели, насколько успешно он улучшает команду и ее понимание ХР. Но каждый из этих принципов действительно помогает правильно понять ХР. Самоподобие не исключение.
Оно означает, что одни и те же паттерны проявляются в различных масштабах – от очень больших до совсем маленьких. В хорошей архитектуре программного решения существует большое количество самоподобия. Основательное, надежное и простое в использовании программное обеспечение часто состоит из слоев с точно такими же характеристиками, а те в свою очередь, – из таких же модулей. И когда вы открываете один из этих модулей и смотрите на код, то что вы там увидите? Правильно – основательный, надежный и легкий для понимания код.
Самоподобие присутствует и при энергичной работе: команды достигают состояния потока, когда мировоззрение отдельных разработчиков также соответствует этому состоянию. Самоподобие можно найти и в планировании. Разработчик планирует тесты, затем пишет код, а команда планирует функции и выполняет недельный цикл, она также определяет тематику работы и начинает квартальный цикл.
Так нужно ли искать самоподобие в каждом аспекте вашей работы? Конечно, нет, это просто один из принципов. Но это поможет выявить закономерности, которые дадут лучшее понимание того, как именно идет работа над вашим проектом. И любой другой принцип делает то же самое. Так что не отмахивайтесь от них – это ценные инструменты, которые помогут понять методологию. Если они кажутся лишними, то постарайтесь подумать о том, какое отношение они имеют к работе, которую вы выполняете. Это поможет глубже воспринять ХР.

 

Я читал в интернете, что разработка через тестирование умерла. Это правда?
Разработка через тестирование – это инструмент. Говорить, что он умер, так же нелепо, как сообщить о смерти отверток. Многие команды используют разработку через тестирование каждый день и находят ее успешной. До тех пор, пока команды используют эту методику, она остается живой и активной.
Однако можно обсуждать этот вопрос на более глубоком уровне. Одна из причин, по которой разработчики (особенно имеющие большой опыт использования Agile и ХР) поднимают этот вопрос, заключается в том, что существуют команды, воспринимающие TDD не только как инструмент, но и как разновидность верования. Они сосредоточиваются на тестах как на конечной цели, а не как на средстве для создания лучшего программного обеспечения. Такие команды попадают в платформенную ловушку, затрачивая много времени на создание обширных и сложных платформ для тестирования. Разработка через тестирование предполагает помощь команде в сохранении простого исходного кода. Но когда он становится сложным, это значит, что-то пошло не так.
Те, кто заявляет, что «TDD умерла», считают, будто ХР-практики (особенно TDD и парное программирование) создают значительное эмоциональное сопротивление у команд, которые недостаточно знакомы с ними.
Команда, использующая ХР, не считает своей целью написание модульных тестов, так же как водопадные команды не рассматривают в качестве цели создание спецификаций. Главное – собрать работающее программное обеспечение, а TDD и спецификации лишь средства для достижения этой цели.
Есть еще один аспект, который поможет вам лучше разобраться в этом споре.
В главах 6 и 7 мы использовали термины «разработка через тестирование» и «разработка с опережающим написанием тестов» как синонимы. В течение многих лет их именно так и рассматривали, и мы решили, что для понимания концепции это упрощение было допустимо. Но некоторые люди рассматривают разработку с опережающим написанием тестов лишь как создание сначала тестов, а потом кода, в то время как TDD подразумевает более широкий подход к проектированию.
Надо ли писать тесты первыми, чтобы получить хорошо спроектированный код? Конечно, нет – многие команды делают прекрасный код без использования TDD. Но является ли TDD ценным инструментом для сборки хорошо продуманного кода? Безусловно. Если вы еще не применяли TDD, то без труда придумаете гипотетические причины не делать этого («Мне нравится делать наброски того, что я создаю, и видеть, как оно скрепляется вместе. В противном случае мне незачем писать тесты, поэтому ясно, что при применении TDD мне придется идти на компромисс!»)
Но дело в том, что многие команды используют TDD в строгом соответствии с методикой, а многие из этих гипотетических причин исчезают, когда вы делаете серьезные попытки применить эту практику.
Полезно заглянуть в статью, с которой началась большая дискуссия на тему, мертва ли TDD, и не пропустить ответ Кента Бека, опубликованный в Facebook. В нем он подробно объясняет, как TDD помогает решать проблемы программирования и лучше проектировать архитектуру.
Покойся с миром, TDD
29 апреля 2014 года, 11:10
DHH послал TDD на свалку истории . Мне грустно прежде всего не потому, что я спас TDD от попадания на свалку истории, а потому, что теперь нужны новые методы, чтобы я мог решить многие проблемы текущего программирования.

• Чрезмерное проектирование. У меня есть склонность «забираться» в функциональность, о которой я «знаю», что она «понадобится». Превращения одного теста из красного в зеленый (параллельно со списком будущих тестов) мне достаточно, чтобы избавиться от этого «копания». Мне нужно найти новый способ, чтобы оставаться сосредоточенным.
• Обратная связь по API. Мне нужно найти новый способ, чтобы получать быструю обратную связь о моих решениях, принятых по API.
Логические ошибки. Мне нужно найти новый способ, чтобы ловить эти надоедливые ошибки, которые я так часто делаю.
• Документация. Мне нужно найти новый способ сообщать коллегам, каким я предполагаю использование API, и записывать мои мысли во время разработки.
• Ощущение подавленности. Я действительно буду скучать по тем временам, когда, применяя TDD, я, написав тест, мог представить реализацию, даже если поначалу у меня не было никаких мыслей по этому поводу. Мне нужно найти новый способ, чтобы сделать следующий шаг к вершине.
• Размышление о том, как отделить интерфейс от реализации. У меня есть склонность загрязнять решения по дизайну API его предположительными реализациями. Мне нужно найти новый способ разделения двух уровней мышления, обеспечивая оперативную обратную связь между ними.
• Соглашение. Мне нужно найти новый путь, чтобы точно передавать свои мысли партнерам по программированию о тех проблемах, которые я решаю.
• Тревога. Скорее всего, я буду больше всего скучать по возможности, которую дает мне мгновенная кнопка TDD «Все хорошо?».
Я уверен, что найду другие способы решить эти проблемы. Со временем. Боль исчезнет. Прощай, TDD, старый друг.
(Facebook, страничка Кента Бека)
Так каков же будет вердикт? Одни команды пробовали использовать разработку через тестирование и нашли ее очень полезной. Другие считают, что ее трудно внедрить. Самый лучший способ решить это для себя – попробовать. Если вы попробуете – а мы очень рекомендуем это сделать, – то для получения хороших результатов, прежде всего, нужно быть очень осторожными, чтобы не попасть в платформенную ловушку во время создания модульных тестов.
Кент Бек отвечал на эссе Давида Хейнемейера Ханссона (известного в сообществе Ruby как DHH), создателя Ruby on Rails и одного из идеологов agile-сообщества, озаглавленное так: «TDD умерла. Да здравствует тестирование!». DHH смог идентифицировать некоторые важные признаки модульных тестов, которые попали в платформенную ловушку.
Первоочередное тестирование модулей приводит к чрезмерно сложной сети промежуточных объектов и косвенным обращениям в запросе, чтобы избежать их медленной работы. Как попадание в базу данных. Или файловый ввод-вывод. Или тестирование в браузере всей системы. Это породило некоторых архитектурных монстров. Густые джунгли сервисных объектов, паттернов команд и много чего еще.
Я редко разрабатываю модульные тесты в традиционном смысле этого слова, где все зависимости являются смешными и тысячи тестов можно выполнить в считаные секунды.
Вам это описание знакомо? Должно быть, поскольку оно очень похоже на примеры кода «с душком», о котором вы узнали в этой главе. Модульные тесты подвержены точно таким же проблемам сложности, какие могут повлиять на любой код. Если вы поймаете себя на создании очень сложных модульных тестов, то вполне возможно, что вы попали в такую же ловушку, которую так хорошо сформулировал DHH.
DHH также отмечает важную особенность TDD.
Это было не так. Когда я впервые открыл для себя TDD, это было похоже на вежливое приглашение в лучший мир написания программного обеспечения.
Разум заставляет вас применять практику тестирования там, где тестирования никогда не было. TDD открыла для меня спокойствие, вызываемое хорошо протестированным кодом, и блаженство, с которым я мог вносить изменения в программное обеспечение.
Предваряющее тестирование было замечательным курсом тренировок, который научил меня думать о тестировании на более глубоком уровне, но который я быстро завершил.
Это отличный повод, чтобы попробовать TDD. Это поможет вам думать о тестировании на более глубоком уровне, как это делает Кент Бек в упомянутом сообщении на Facebook. Единственный ли это способ для реализации перечисленных в сообщении приемов? Нет. Но он очень эффективен и поэтому является очень важной частью XP.

 

Что вы можете сделать сегодня
Предлагаем несколько вариантов действий, которые вы можете предпринять уже сегодня (самостоятельно или вместе с командой).

 

• Если вы разработчик, то попробуйте сделать рефакторинг своего кода. Возможно, вы уже используете IDE, которая имеет встроенные инструменты рефакторинга. Сможете ли вы найти простой способ изменить структуру кода, с которым вы работаете сейчас, упростив его, но не меняя поведения?
• Посетите сайт WikiWikiWeb и прочитайте страницу о коде «с душком». Можете ли вы найти подобный код у себя? Если нет, то всмотритесь внимательнее.
• Легко ли проверить ваш исходный код из системы управления версиями и собрать его? Если вам необходимо выполнить много различных действий, то попробуйте найти способ автоматизировать этот процесс при помощи скрипта сборки. Каждый шаг в сторону упрощения проверки и сборки делает вашу жизнь проще в долгосрочной перспективе.
• Вы уже пробовали разработку через тестирование? Нет? Попробуйте. Возьмите пользовательскую историю или функцию, которую вас просили создать. Перед тем как приступить к написанию кода, придумайте один-два теста для того модуля, который вы собираетесь написать. Вам не нужно увлекаться полным набором тестов. Достаточно одного или двух, а затем соберите код, который пройдет их.

 

Где вы можете узнать больше
Ниже перечислены ресурсы, которые помогут вам узнать больше об идеях, описанных в этой главе.

 

• Вы можете узнать больше о простоте, инкрементальной архитектуре и других целостных практиках в книге Кента Бека и Синтии Андрес Extreme Programming Explained: Embrace Change (Addison-Wesley, 2004).
• Можно узнать больше о рефакторинге в книге Мартина Фаулера, Кента Бека, Джона Бранта и Уильяма Апдайка «Рефакторинг. Улучшение существующего кода» (М.: Символ-Плюс, 2008).
• Узнайте больше о потоке и о том, как создавать более энергичную рабочую среду, в книге Тома Демарко и Тимоти Листера «Человеческий фактор. Успешные проекты и команды» (М.: Символ-Плюс, 2014).

 

Подсказки
Здесь мы предлагаем советы для agile-коучей, помогающих своей команде разрабатывать идеи этой главы.

 

• Попадает ли ваша команда в платформенную ловушку? Пробует ли она решать большие абстрактные проблемы вместо маленьких и конкретных? Помогите ей осознать, что это сложное мышление. Изменить его на простое – один из самых важных способов, ведущих команду к принятию ХР.
• Поговорите с командой о YAGNI («Вам это не понадобится»). Помогите ей найти хотя бы один фрагмент кода, который на самом деле не нужен. Многие команды собирают целые функции, никогда никем не востребованные и не используемые. А у вашей команды есть такой опыт?
• Выясните, что вызывает чувство дискомфорта у членов команды во время применения практики разработки через тестирование или парного программирования, и помогите им устранить это ощущение. Избегайте длительных философских дебатов о достоинствах практики, вместо этого сосредоточьтесь на поиске конкретных проблем команды и практиках, которые помогут их решить. Опыт – лучший способ преодоления защитной реакции и дискомфорта. Иногда для этого сотруднику требуется час или два.
• Некоторые практики – особенно разработка через тестирование – кажутся привлекательными только одному члену команды. Он исполнен энтузиазма, но его благие намерения могут восприниматься коллегами как издевательство или фанатизм. Напомните ему, что для получения нового навыка требуются время и усилия, но пока никто в команде этим не занимался. Терпение – это то, чему научить труднее всего, поэтому будьте терпеливы.
Назад: Инкрементальная архитектура и целостные XP-практики
Дальше: Глава 8. Lean, ликвидация потерь и целостная картина