Представьте себе мир, в котором

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

Как такое возможно? Применяя эти простые шаги к процессу разработки программного обеспечения, вы избежите ада выпуска и интеграции.

Разработка на основе мастера / магистрали

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

Другие положительные побочные эффекты заключаются в том, что вам не нужен отдельный конвейер сборки / интеграции на сервере CI для каждой ветви, а сложность использования SCM минимальна.

Освободите каждую фиксацию / отправку в продакшн

Каждый раз, когда разработчик фиксирует и продвигает свои изменения (что следует делать не реже одного раза в день), выпускайте его в рабочую среду. Конечно, вам придется выполнить обычную автоматическую единицу, интеграцию, приемочное тестирование и, в идеале, канареечное развертывание, если все пройдет - дерзайте!

Но… как убедиться, что все работает? Что делать, если функция не доработана?

Переключение функций

Когда вы пишете новый код для функции, всегда помещайте его в переключатель функции. Это простой оператор if-else для стратегической позиции, обычно очень далеко в интерфейсе
if (featureManager.isEnable ('my-new-fancy-feature'))… новый код
иначе… старый код

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

  • дата начала и окончания
  • включен только для некоторых IP-адресов (внутренние офисные IP-адреса)
  • включен только для определенного процента пользователей (для постепенного развертывания)
  • включен только для администраторов (для тестирования функции и принятия в действующей системе)

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

Чтобы избежать распространенных ошибок, просто следуйте этим простым советам.

  • всегда писать и запускать модульные тесты для обоих состояний переключателя функций - включено и отключено
  • подготовить и спланировать задачу по очистке старых переключателей функций. Как только функция включена, переключатель и старый код необходимо удалить. Это помогает добавлять комментарии типа `// удалить это при очистке функции XYZ`. Обычно это делается в следующем спринте.
  • Не усложняйте конфигурацию переключателя функций, поэтому людям очень легко определить, активен переключатель или нет. Это позволяет избежать случайной активации функций.

Резюме

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