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