Мнение Этвуда абсолютно правильно, и если сформулировать точнее, то усилия, необходимые для успешного объединения веток, растут экспоненциально по мере роста числа веток. Проблема заключается не только в объеме переделок, необходимых после «ада слияний», но также в том, что обратную связь от конвейера развертывания мы получаем с задержкой. Например, скорее всего, только в конце процесса разработки удастся выполнить тестирование производительности полностью интегрированной системы — непрерывным данный процесс сделать не получится.
Кроме того, если мы повышаем скорость создания кода, увеличивая количество разработчиков, то усиливаем вероятность того, что любое изменение затронет какого-то другого разработчика и увеличит количество сбоев в конвейере развертывания.
Это один из побочных эффектов слияния больших наборов изменений, вызывающих наибольшие сложности: когда слияние трудно, у нас остается меньше возможностей и, кроме того, понижается мотивация улучшать код и выполнять его рефакторинг, поскольку рефакторинг, скорее всего, будет означать, что кому-то придется переделывать работу. Когда такое происходит, желание модифицировать код, имеющий зависимости во всем репозитории кода, заметно ослабевает, хотя (и в этом трагизм ситуации) именно это могло бы дать нам наибольшую отдачу.
Вот как Уорд Каннингем, разработчик первой wiki, впервые описал технический долг: если мы не выполняем агрессивный рефакторинг нашей базы кода, то с течением времени становится все труднее вносить изменения в код и поддерживать его, а это снижает скорость добавления новых функциональных возможностей. Решение этой проблемы — одна из основных причин создания непрерывной интеграции и практики развития кода на базе основной ветки и оптимизации производительности команды вместо индивидуальной производительности.
Контрмеры по отношению к большим пакетам слияний — это организация непрерывной интеграции и методы разработки на базе основной ветки, когда все разработчики фиксируют свой код на основной ветке по меньшей мере один раз в день. Частая фиксация кода значительно уменьшает размер одного пакета, и команда разработчиков оказывается способна выполнить задание за день. Чем чаще разработчики фиксируют код в основной ветке, тем меньше размер пакета и тем ближе мы к теоретическому идеалу штучного потока.
Частая фиксация кода в основной ветке означает: мы можем запускать все автоматические проверки системы программного обеспечения как целого и получать уведомления, если изменение «ломает» работу других частей приложения или вмешивается в работу другого разработчика. И поскольку можно обнаруживать проблемы слияния, пока они невелики, мы способны исправить их быстрее.
Мы даже можем настроить конвейер развертывания так, чтобы он отвергал любые фиксации (например, кода или изменений среды), нарушающие состояние готовности к развертыванию. Этот способ называется
Принятая практика ежедневной фиксации кода также заставляет нас разделять работу на небольшие кусочки, в то же время обеспечивая нахождение основной ветки в рабочем состоянии, годном к релизу.
И система контроля версий становится неотъемлемым механизмом обмена информацией внутри команды — каждый ее член лучше понимает систему в целом, находится в курсе состояния конвейера развертывания, и они могут помочь друг другу, когда он ломается. В результате получаем более высокое качество и небольшое время разработки.
Рассмотрев эти методы, мы можем теперь снова изменить определение состояния «сделано» (выделено жирным шрифтом): «В конце каждого интервала разработки мы должны иметь интегрированный, протестированный, рабочий и потенциально готовый к поставке (что демонстрируется запуском в среде, близкой к производственной) код, созданный на базе основной ветки процессом, “запускаемым одним щелчком мыши”, и проверенный автоматическими тестами».
Пересмотренное определение поможет нам в дальнейшем гарантировать, что написанный нами код всегда пройдет тестирование и будет пригоден к развертыванию. Поддерживая код в готовности к развертыванию, мы способны исключить традиционные методы, когда тестирование кода и его стабилизация осуществляются отдельными фазами в конце проекта.