Автоматизация для программистов: Часть 2. Антишаблоны непрерывной интеграции

Как не стоит поступать, если вы решили внедрить CI

Хотя постоянная интеграция (continuous integration — далее CI) может быть весьма эффективным средством снижения рисков проекта, она требует особого внимания к повседневному процессу создания программного кода. Во второй части статьи из двух частей, посвящённой антишаблонам непрерывной интеграции, эксперт по автоматизации и соавтор книги Continuous Integration: Improving Software Quality and Reducing RiskПол Дювал продолжает рассказывать про антишаблоны непрерывной интеграции, и, что гораздо важнее, показывает, как их избежать.

Пол Дювал, директор по технологиям, Stelligent Incorporated

Пол Дювал (Paul Duvall) – директор по технологиям консалтинговой компании Stelligent Incorporated и идейный лидер, помогающий командам разработчиков оптимизировать гибкую (agile) разработку ПО. Он является соавтором книги Continuous Integration: Improving Software Quality and Reducing Risk (Addison-Wesley Signature Series, 2007). Он также участвовал в написании книг UML 2 Toolkit (Wiley, 2003) и No Fluff Just Stuff Anthology (Pragmatic Programmers, 2007).



07.12.2009

Об этой серии статей

Будучи разработчиками, мы автоматизируем процессы для конечных пользователей; но часто не замечаем возможностей автоматизировать наш собственный процесс разработки. Серия статей Автоматизация для программистов исследует практические аспекты автоматизации процессов программирования и рассказывает, когда и как можно успешно применять автоматизацию.

В первой статье этой серии, состоящей из двух частей, я описывал следующие шесть антишаблонов непрерывной интеграции:

  • Редкие сохранения изменений, приводящие к задержкам интеграции
  • Неработоспособные сборки, не дающие командам переходить к другим задачам
  • Минимальная обратная связь, препятствующая совершению действий
  • Чрезмерная обратная связь, заставляющая сотрудников игнорировать сообщения
  • Применение медленного компьютера для сборки, задерживающее получение обратной связи
  • Использование перегруженных сборок, также задерживающее обратную связь

Эти антишаблоны препятствуют получению преимуществ от использования непрерывной интеграции или задерживают их появление. В этой второй части статьи я раскрою еще пять таких же вредных привычек:

  • Сохранение изменений откладывается до конца дня, что приводит к затормаживанию сохранения изменений, а в итоге — к неработоспособным сборкам и разочарованию разработчиков
  • Сборки, состоящие из минималистичных автоматизированных процессов, которые всегда заканчиваются успешно, что ведет к постоянной неосведомлённости (Continuous Ignorance) и отсрочке выявления проблем интеграции
  • Предпочтительное использование запланированных сборок вместо частых сборок при каждом изменении исходного текста программы, что задерживает исправление ошибок в программе
  • Упование на то, что программа работает на моей машине, — впоследствии выясняется, что в других средах возникают ошибки
  • Сохранение артефактов старых сборок, что ведет к загрязнению среды, и к появлению ложных положительных или отрицательных результатов

И еще раз: чтобы в полной мере реализовать многочисленные преимущества непрерывной интеграции, необходимо отдавать себе отчёт о существовании этих антишаблонов — и избегать их.

Устранение узких мест при фиксации изменений

Название: Задержки при фиксации изменений

Антишаблон: Разработчики фиксируют изменения, сделанные за день, перед уходом в конце рабочего дня, что приводит к ошибкам интеграционной сборки и не дает членам команды вовремя уйти домой.

Что такое интеграционная сборка?

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

Решение: Часто фиксировать изменения в коде программы на протяжении дня.

Задержки при фиксации изменений являются разновидностью антишаблона с редкими фиксациями изменений. Предполагается, что регистрация изменений текста программы делается не реже раза в день. Но проблема состоит в том, что все регистрируют изменения одновременно. Слава Имешев (Slava Imeshev) в своей публикации на CM Crossroads отмечает, что большинство отказов сборок происходит между 17:00 и 20:00 (и в меньшей степени — в обеденное время). Называя это явление "пятичасовой регистрацией изменений", Имешев связывает его со стремлением разработчиков делать регистрацию изменений в своём коде к концу дня (см. Ресурсы).

Около пяти

"Пятичасовая регистрация изменений"— это быстрый способ потерять друзей, если в команде придерживаются правила, что никто не уходит домой, пока все изменения не будут внесены и не сделана сборка. Даже просто ожидание передачи изменений может быть утомительным. Представьте теперь, что случится, если сборка выдаст ошибку. Думаю, что будет много звонков домой с объяснениями, почему придется задержаться на работе ...опять.

На рисунке 1 изображена типичная хронология фиксации изменений командой программистов. Обратите внимание, что фиксации изменений в репозитарии группируются вокруг обеденного перерыва и перед окончанием рабочего дня.

Рисунок 1. Узкие места при фиксации изменений
Узкие места при фиксации изменений

Решение этой серьёзной проблемы заключается, конечно, в том, чтобы чаще фиксировать изменения! При таком подходе получатся меньшие по объему, но более частые интеграционные сборки, и когда сборка выдаст ошибку, то она, вероятно, будет небольшой и ее легче будет исправить.

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


Несчастливое неведение

Название: Постоянная неосведомлённость (Continuous Ignorance)

Антишаблон: Раз сборка прошла без ошибок, все считают, что полученное программное обеспечение работает отлично. На самом деле сборка состояла всего лишь из компиляции и тестирования нескольких модулей.

Решение: Делать полную интеграционную сборку с каждым изменением в репозитарии системы контроля версий.

Иногда у разработчиков может возникнуть ложное чувство безопасности, когда получается одна успешная сборка за другой. На самом деле, когда ошибки сборки возникают редко, это почти верный знак того, что команда ведет себя в соответствии с антишаблоном Постоянная неосведомлённость. Если интеграционные сборки всегда успешны, то, вероятно, не делается достаточно подробная проверка кода! Чем меньше делает сборка, тем меньше добывается информации о том, действительно ли программное обеспечение работает так, как ожидается.

Неосведомлённость при тестировании

Антишаблон «постоянной неосведомлённости» появляется, когда неработающий тест комментируется в попытке принудительно сделать сборку работающей, вместо того чтобы исправить источник проблемы. Хотя такой подход и приводит к успешной интеграционной сборке, это всего лишь еще одна тактика отсрочки, используемая для откладывания того, что потом, весьма вероятно, станет гораздо большей проблемой.

Полные сборки как путь к прозрению

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

Рисунок 2. Делайте обстоятельные сборки
Делайте обстоятельные сборки

Оптимизируйте сборки

Если включить дополнительные процессы: интеграцию с базой данных, тестирование у разработчиков (модулей, компонентов, функциональное тестирование и так далее), автоматизированную инспекцию программного кода (соответствие стандартам программирования, цикломатическая сложность, наличие дублирования кода) и установочные дистрибутивы, — то появляется гораздо больше возможностей определить на ранней стадии цикла разработки, работает ли программное обеспечение на самом деле. Но имейте в виду, что чем больше вы делаете добавлений к интеграционной сборке, тем медленнее будет обратная связь. Следовательно, вероятно, полезно будет создать конвейеры сборки для запуска более медленных процессов после начальной сборки по фиксации изменений — это создаст благоприятные возможности для более быстрой обратной связи и обеспечит более гибкий механизм оценки программного обеспечения.


Пересмотрите расписание сборок

Название: Сборки по расписанию

Антишаблон: Сборки делаются ежедневно, еженедельно или по какому-либо другому графику, а не после каждого изменения.

Решение: Запускать сборку при каждом изменении исходного текста в репозитарии

Непрерывная интеграция подразумевает частую интеграцию программных средств — под словом «частая» я имею в виду всякий раз, когда изменяется код программы. По моему мнению, это самый быстрый способ обнаружить проблемы на их ранней стадии. Раннее обнаружение проблем — это хорошо. Во-первых, это экономит ваши деньги. Во-вторых, это действительно помогает создавать хорошие программы.

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

Эффективное проведение непрерывной интеграции требует упреждающего подхода — когда сборка оказывается нерабочей, проблемы необходимо исправлять немедленно. Принцип сборок по расписанию препятствует упреждающим действиям и приводит к подходу "я исправлю это, когда дойдут руки", что полностью противоречит сути непрерывной интеграции.

Перейти со сборок по расписанию на более частый график не сложнее, чем правильно настроить сервер непрерывной интеграции. Например, в листинге 1 показан скрипт CruiseControl, который каждые две минуты опрашивает репозитарий системы контроля версий. Если обнаруживается изменение, CruiseControl запускает сборку.

Листинг 1. Сборка при каждом изменении
  ...
  <schedule interval="120">
    <ant anthome="${cc.ant.dir}" buildfile="build-${project.name}.xml"/>
  </schedule>
  ...

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


Но ведь на моей машине оно работает!

Название: Работает на моей машине

Антишаблон: Делаются частные сборки, которые работоспособны только на машине разработчика, а затем обнаруживается, что изменения не работают в других средах.

Решение: Использовать отдельную машину для интеграционных сборок, запуская сборку при каждом изменении, внесенном в репозитарий системы контроля версий.

Представим, что разработчик сделал изменение в тексте программы, запустил свою сборку (с помощью IDE или Ant), и после того, как все заработало так, как должно, сохранил свои изменения в репозитарии системы контроля версий. Спустя несколько дней кто-нибудь разворачивает программу в другой среде и сообщает этому разработчику, что его изменения не работают. Тогда он снова запускает приложение на своей рабочей станции — о чудо! все отлично работает, и он говорит: "Но у меня оно работает!"

Случалось такое? Если нет, готовьтесь, скорее всего случится. У такой неприятной ситуации может быть много причин, но обычно виновата забывчивость: вы забыли добавить новый файл в репозитарий системы контроля версий или некоторая специфическая настройка, которая существует на компьютере разработчика, отсутствует в другой среде.

Мир за пределами рабочей среды разработчика

Название: Сборка только с помощью IDE

Антишаблон: Разработчик делает частную сборку с помощью IDE (которая работает локально) на своей рабочей станции, а затем в другой среде обнаруживаются ошибки.

Решение: Нужно создать скрипт для сборки и поместить его в репозитарий системы управления версиями. Запускайте этот скрипт при каждом изменении.

Нет ничего плохого в том, чтобы использовать IDE для написания текста программы или создания сборочных скриптов. IDE делают работу более эффективной. Но если процессы сборки так тесно связаны с IDE, что невозможно запустить интеграционную сборку без установки IDE в среде развертывания, возникает проблема. Это происходит потому, что группы по эксплуатации обычно не устанавливают IDE в тестовой и в рабочей средах. В противном случае для запуска интеграционной сборки потребовалось бы ручное конфигурирование IDE, что может привести к несовместимости между средами и к ошибкам сборки. Кроме того, зависимость сборки от IDE может задержать обнаружение проблем с конфигурацией до конца процесса разработки, поскольку в тестовой и рабочей средах зависимости от IDE исчезают.

Все, что нужно сделать, чтобы решить проблему сборки только с помощью IDE — это создать скрипт для сборки (его так же легко можно использовать и в IDE). Этот же скрипт может затем стать главным механизмом для интеграционных сборок — независимо от среды.

Близорукость и разработчик

Название: Близорукая среда

Антишаблон: Уверенность, что если сборка работает в одной среде, то заработает и в других.

Решение: Определить поведение сборки в целевых средах сборки; кроме того, выделить зависящие от среды данные в файлы .properties.

Антишаблон «близорукая среда» отражает такой склад ума разработчиков, при котором ошибочно предполагается, что если программа работает в какой-то одной среде, то работа сделана. Чтобы бороться с таким менталитетом, в системах с непрерывной интеграцией не должно быть допущений (в разумных пределах). Для уменьшения числа допущений нужно убрать ограничения, связанные с платформой, и сделать их заменяемыми, например, с помощью файлов свойств.

Если сборка предназначена как для среды Windows®, так и Linux®, она, очевидно, не будет работать в Linux, если в ней имеются ссылки на диск C. Если в сборке используется машинно-зависимая переменная среды (например, GLOBUS_LOCATION), она не будет работать, если эти переменные не будут настроены в другой среде. В таких случаях достаточно изменить эти ссылки на переменные, которые можно заменить во время сборки.

Фрагмент Ant XML в листинге 2 демонстрирует, как добавить файл .properties, содержащий значения переменных среды:

Листинг 2. Ссылка на файл с переменными среды в скрипте сборки
<property file="${basedir}/TEST.properties" />

В properties-файле из листинга 3 приводятся данные, характерные для среды развертывания. Обратите внимание, как этот файл уменьшает число допущений в самой сборке, выделяя такую информацию, как параметры соединения с базой данных, местоположение Web-контейнера, имена серверов, идентификационная информация.

Листинг 3. Определение данных в properties-файле
database.host.name=integratebutton.com
database.username=myusername
database.password=mypassword
database.port=3306
jboss.home=/usr/local/jboss/server/default
jboss.temp.dir=/tmp
jboss.server.hostname=integratebutton.com
jboss.server.port=8080
jboss.server.jndi.port=1099

Все действия сборки следует хранить в целях (например, цели Ant). Любые данные, используемые более одного раза в одном и том же скрипте, следует определять в виде свойства. Любые данные, которые меняются от одной машины к другой, должны быть вынесены в файл .properties. Следуя этому простому совету, можно достичь максимальной гибкости при минимальных проблемах.


Очистите свою среду

Название: Загрязненная среда

Антишаблон: Для экономии времени запускается инкрементная сборка; однако оставшийся от предыдущей сборки артефакт дает ложно положительный (или ложно отрицательный) результат.

Решение: Перед запуском сборки удалите артефакты от предыдущей сборки. Приведите сервер и конфигурационную информацию в исходное состояние.

Мойте посуду перед едой

Мало что вызывает большее разочарование, чем сбой сборки из-за неудалённых артефактов предыдущей сборки. Такими артефактами могут быть ранее развернутые WAR-файлы, неправильные версии JAR или обновления базы данных. С другой стороны, еще более неприятная ситуация возникает, когда у разработчиков складывается ложное чувство успешности из-за того, что оставшиеся в среде сборки ранее собранные артефакты приводят к удачной сборке.

Исключительно важно приводить среду в известное состояние перед любыми действиями, связанными со сборкой. На практике при сборке программного обеспечения я придерживаюсь тактики «выжженной земли». В листинге 4 приводится простой пример удаления каталогов с предыдущими журналами, дистрибутивами и файлами отчетов с помощью задачи Ant delete task. Это резко уменьшает вероятность ложно положительных или ложно отрицательных результатов сборки.

Листинг 4. Удаление каталогов через Ant
<target name="clean">
  <delete dir="${logs.dir}" />    
  <delete dir="${dist.dir}" />    
  <delete dir="${reports.dir}" />    
  <delete file="cobertura.ser" />     
</target>

Этот упрощенный код — «выжигание» среды может также включать удаление старых файлов классов и ранее развернутых файлов EAR/WAR, приведение базы данных в известное состояние (например, удаление и создание заново таблиц), повторную инициализацию путей к классам, а также исключение использования переменных среды.

Приведение среды развертывания к исходному состоянию

От "выжигания" можно перейти к более продвинутым подходам, например, приведению в фиксированное состояние рабочей среды, в которой осуществляются интеграционные сборки. Для приведения таких сред в исходное состояние каждый компонент и каждый элемент конфигурации автоматизированно удаляется и создается заново. По сравнению с простым удалением старых файлов это может быть труднее сделать в зависимости от сложности среды. Но это можно делать инкрементно. Компонентом может быть база данных, Web- или файловый сервер, закрытое программное обеспечение. Элементом конфигурации может быть переменная среды или изменение в конфигурации базы данных, например, выделение памяти. Тут важна в первую очередь согласованность. Каждая среда, в которой запускаются сборки, должна иметь сходную конфигурацию. Приведение среды развертывания в исходное состояние увеличивает шансы найти причины конкретной проблемы. На рисунке 3 показаны некоторые из компонентов, которые может быть полезно удалить и задать заново аналогичным образом в каждой среде развертывания.

Рисунок 3. Выжигание среды развертывания
Выжигание среды развертывания

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


Как преуспеть в непрерывной интеграции

Надеюсь, мне удалось продемонстрировать, что хотя непрерывная интеграция – замечательный подход к разработке, отдача от неё будет больше, если избегать некоторых антишаблонов. Существуют веские причины к использованию некоторых из этих подходов в процессе разработки, но они могут привести к возникновению антишаблонов. Например, бывают причины для запуска сборки по расписанию. Далее, полезная практика частого обновления изменений в репозитарии может на деле привести к проблемам с затормаживанием обновлений, но это не значит, что частые сохранения являются плохой привычкой. Помните, сами по себе антишаблоны не плохи, но в определенных ситуациях они могут быть вредны.

Ресурсы

Научиться

Получить продукты и технологии

  • Ant: выполняйте сборку Java™-приложений при помощи Ant.(EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=453809
ArticleTitle=Автоматизация для программистов: Часть 2. Антишаблоны непрерывной интеграции
publish-date=12072009