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