• Важная практика
Регулярная интеграция кода каждого разработчика – практика, важная при последовательной разработке.
Как сказал Мартин Фаулер, ярый приверженец этой практики: «Я считаю, что все команды должны использовать непрерывную интеграцию. Инструменты бесплатные. Цена – разве что обучение» [57].
В результате компиляции и объединения всех компонентов получается сборка, используемая для прохождения тестов и получения обратной связи от Владельца продукта. С точки зрения Scrum, эта сборка соответствует микро-инкременту, который к концу спринта станет инкрементом для показа во время обзора.
• Процесс
При каждом коммите разработчика инструмент на сервере интеграции (например, Jenkins или Travis) инициирует цепочку действий [58]. Цепочка обычно следующая:
✓ Компиляция и проверка.
✓ Запуск модульных тестов.
✓ Запуск тестов интеграции и приемочных тестов.
✓ Запуск инструмента, который проверяет синтаксис и корректность кода (например, Linter).
✓ Запуск инструмента, который проверяет качество кода (например, Sonar).
✓ Составление отчета.
✓ Подготовка версии ПО, готовой к использованию.
Непрерывная интеграция гарантирует, что недавно добавленный код отлично сочетается с предыдущим инкрементом.
Если сборка завершается ошибкой, команда останавливается, чтобы как можно быстрее найти проблему и решить ее: нельзя оставлять интеграцию сломанной, одна ошибка обычно влечет за собой следующие.
Чтобы быстро устранить причину поломки, нужно запустить отладчик.
• Когда следует начать?
Желательно овладеть непрерывной интеграцией до начала первого спринта. Если команда решает применить эту практику во время сезона, установка сервера и ПО попадает в бэклог в качестве технической работы.
Команда должна обсудить важность этого подхода с Владельцем продукта, объяснить его преимущества – в частности, более быстрое получение обратной связи. Хороший Владелец продукта обязательно согласится.
• Преимущества
Непрерывная интеграция позволяет в любой момент иметь работающий программный продукт. Это, несомненно, мотивирует как команду, так и пользователей. Она усиливает прозрачность процесса и гарантирует, что результат работы каждого участника виден остальным.
• Непрерывное развертывание
Непрерывную интеграцию продолжает новая практика, которая называется непрерывное развертывание. Она заключается в развертывании результата интеграции в среде, доступной заинтересованным сторонам или конечным пользователям.
Такой ввод в эксплуатацию позволяет получить обратную связь еще быстрее и пройти тесты в более представительной среде.
Чтобы больше об этом узнать, можно обратиться к [Саке, DevOps].
Разработчик, который пишет код, проверяет его кусочек за кусочком: это называется модульным тестом.
Практика разработки через тестирование [Бек, TDD] идет дальше: сначала пишется модульный тест и уже затем – код, достаточный для его прохождения. Такой подход существенно снижает риски при написании кода.
Разработка через тестирование включает рефакторинг.
• Сначала тест
В первую очередь пишется модульный тест для одного компонента, что позволяет определить его желаемое поведение. В принципе, программист пишет только один тест за один раз, после чего – код для его успешного прохождения. С написанным тестом это значительно проще. Программист следует процессу, добавляя новые тесты и минимальный код для их прохождения. Таким образом, он внедряет изменения в продукт.
Эта практика составляет рабочий процесс, в котором ответы на задаваемые вопросы приводят к созданию отличной архитектуры.
Она способствует быстрому проектированию и хорошему знанию кода разработчиками. По сути, это форма неявной документации.
• Рефакторинг
Рефакторинг – это процесс улучшения кода без изменения его поведения. Улучшение качества достигается за счет упрощения и оптимизации текущего решения: команда убирает дублирование кода и делает его более простым и легким для восприятия. И, следовательно, для поддержания.
После каждого изменения необходимо снова проводить тесты, чтобы убедиться: поведение кода осталось прежним. Рефакторинг может выполняться без предварительной разработки тестов, но именно в объединении этих процессов в одну формулу состоит принцип разработки через тестирование.
TDD = Написание теста в первую очередь + рефакторинг.
Внимание: помимо общего кода, это относится и к коду теста.
Рисунок 19.1 – Практика разработки через тестирование
• Когда следует начать?
Для нового ПО – чтобы избежать технического долга
После формирования команды лучшим вариантом будет сразу создать условия для разработки через тестирования с самого начала работы над продуктом, еще до старта первого спринта первого сезона. Желательный уровень, на котором применять данную практику, определяется в критериях завершенности.
Задачи, касающиеся модульных тестов, в плане спринта могут быть указаны отдельно или включены в блок задач, относящихся к коду. Это зависит от опыта команды: если среди участников новички, лучше будет сделать отдельную запись.
Для существующего ПО – чтобы погасить технический долг
Если команда работает над существующим программным обеспечением, вероятно, присутствуют части без модульных тестов, которые нуждаются в рефакторинге.
Встает вопрос о способах возврата технического долга.
Прежде чем приступить непосредственно к погашению этого долга, следует определить компоненты, нуждающиеся в рефакторинге, и порядок работы над ними.
Рефакторинг и написание тестов требуют времени, так как обычно код сложно протестировать. Поэтому все действия, направленные на улучшение качества кода, помещаются в бэклог. Владелец продукта должен позаботиться, чтобы они были выполнены в нужное время, лучше – как можно раньше.
Парное программирование – это практика, заключающаяся в работе двух разработчиков за одной рабочей станцией с целью улучшения качества кода.
Один разработчик сидит за клавиатурой, другой следит за экраном, предлагая идеи. Совместная работа выполняется с двух точек зрения: первая направлена на детали кода, а вторая – на общую структуру.
Рисунок 19.2 – Игра в четыре руки
• Когда следует начать?
Момент начала использования этой практики – решение команды. Работать таким образом весь день невозможно, да и не требуется: процесс довольно интенсивный и напряженный. Необходимо регулярно меняться ролями внутри пары и между парами внутри команды. Обсуждать перемещения можно во время ежедневных схваток.
Эта практика особенно рекомендуется для сложных частей ПО.
• Преимущества
Работа в паре ориентирована на улучшение качества продукта: технический долг всегда меньше в отношении тех частей, что реализованы двумя участниками.
Такой подход также упрощает обмен знаниями и компетенциями в команде.
Парное программирование – квинтэссенция совместной работы.
Следует отметить, что работа в паре – это форма, образовавшаяся на основе паттерна роение, о котором мы узнали в главе, посвященной планированию.
• Что дальше?
Пинг-понг программирование состоит в постоянной ротации двух участников: один пишет тест и передает управление другому, второй пишет код и делает рефакторинг, затем пишет тест – и они меняются.
Моб-программирование [59] расширяет эту практику до размеров всей команды.
Она может распространяться и за пределами команды разработчиков: пары могут состоять из участника команды и Владельца продукта или даже кого-то из заинтересованных сторон.
Вот почему работа в паре – это, скорее, практика совместной работы, нежели программирования.
19.2 Практики, относящиеся к проектированию
Ранее различали этапы предварительного проектирования и рабочего проекта. Сейчас широко используется термин программная архитектура. Архитектура относится к организации компонентов и их взаимодействию. Проще говоря, архитектура глобальна и позволяет направлять выбор при проектировании компонента или разрабатывать историю.
Если судить по стереотипам, традиционный подход склоняется к тому, чтобы иметь всю архитектуру с самого начала, а при Agile-методологии архитектура развивается с каждой итерацией.
В Scrum-фреймворке, может, и не рекомендуется замораживать архитектуру слишком рано, но и не запрещается прорабатывать ее сразу во время прелюдии. Все зависит от контекста. В любом случае, не стоит выходить за рамки текущего сезона и принимать преждевременных решений.
Чтобы снизить риски в отношении архитектуры, команда разрабатывает историю, значимую с точки зрения архитектуры, то есть касающуюся всех основных компонентов.
Какая бы часть архитектуры ни была сделана до первого спринта, нужно помнить, что работы прибавится во время спринтов: архитектура эволюционирует, и невозможно все создать заранее и сразу ввиду сложности компьютерных систем.
Большие задачи заносятся в бэклог отдельными пунктами. Работа, связанная с архитектурой, может потребовать поддержки со стороны эксперта. Нужно предусмотреть это заранее, чтобы гарантировать его доступность. Как и в случае с остальными историями, не имеющими видимой ценности, необходимо обсудить важность этой работы с Владельцем продукта и приоритизировать задачи.