Что такое feature toggle
Что такое feature toggle или как избавиться от мучительных мёржей и долгоживущих веток?
Проблема
Представьте, что циклы разработки вашей команды длятся по две недели, а реализация новой фичи потребует от команды 3 месяца разработки. На первый взгляд, есть две возможные схемы действий:
Использование feature switcher-ов для решения проблем
Такая проблема встречается в разработке довольно часто и есть изящное решение, позволяющее взять лучшее от описанных выше подходов — feature toggle или feature switcher.
По сути, feature switcher — это boolean флаг, который хранится в базе данных и содержит информацию о том, должна быть включена та или иная фича или нет. Значение этого флага может быть извлечено из базы данных по ключу. Удобство использования feature switcher-ов заключается в том, что они могут быть легко изменены бизнес-пользователем во время runtime через панель администратора без необходимости заново деплоить приложение.
Ниже приведен пример использования feature toggle на языке Java:
В примере выше configurationManager — это класс, позволяющий извлечь значение определенного feature switcher-а из базы данных по его ключу.
Также, при помощи feature switcher-ов, можно отображать/скрывать определенные элементы на фронтенде. Для этого придется положить значение флага в Model и передать его на View как это показано ниже:
После чего использовать переданное значение для рендеринга того или иного HTML кода:
Виды feature switcher-ов
Описанный концепт использования feature switcher-ов — это лишь один возможный случай использования и такие feature switcher-ы называются release toggles. Всего выделяют 3 разных вида feature switcher-ов:
Проблемы использования feature toggle-ов
Поскольку я работаю на проекте, где активно используются feature toggle-ы, то кроме очевидных достоинств их использования я начал замечать и проблемы, связанные с ними:
Решения некоторых из описанных проблем
Помочь решить вышеописанные проблемы могут следующие действия:
Итоги
Feature switcher — очень простой и одновременно мощный механизм, позволяющий избегать монструозных коммитов, легко менять поведения приложения или собирать несколько разных приложений на одной кодовой базе, используя разную конфигурацию feature toggle-ов.
Однако, стоит также помнить, что этот паттерн разработки имеет некоторые недостатки, которые выливаются в трудночитаемый и трудно поддерживаемый код, поэтому следует избегать чрезмерного использования этого паттерна и периодически проводить документирование feature switcher-ов и их ревизию, чтобы удалять неиспользуемые и, как следствие, очищать проект от “мёртвого” кода.
Что такое feature toggle или как избавиться от мучительных мёржей и долгоживущих веток?
Допустим, вы хотите разработать новую фичу, но не уверены, что она понравится пользователям, и вам нужно иметь способ безболезненно её скрыть. Или предположим, что вы работаете над новой большой фичей и хотите избежать монстр-коммитов. Или просто хочется сделать поведение сайта легко конфигурируемым. Как можно решить все эти проблемы, читайте под катом.
Проблема
Представьте, что циклы разработки вашей команды длятся по две недели, а реализация новой фичи потребует от команды 3 месяца разработки. На первый взгляд, есть две возможные схемы действий:
Использование feature switcher-ов для решения проблем
Такая проблема встречается в разработке довольно часто и есть изящное решение, позволяющее взять лучшее от описанных выше подходов — feature toggle или feature switcher.
По сути, feature switcher — это boolean флаг, который хранится в базе данных и содержит информацию о том, должна быть включена та или иная фича или нет. Значение этого флага может быть извлечено из базы данных по ключу. Удобство использования feature switcher-ов заключается в том, что они могут быть легко изменены бизнес-пользователем во время runtime через панель администратора без необходимости заново деплоить приложение.
Ниже приведен пример использования feature toggle на языке Java:
В примере выше configurationManager — это класс, позволяющий извлечь значение определенного feature switcher-а из базы данных по его ключу.
Также, при помощи feature switcher-ов, можно отображать/скрывать определенные элементы на фронтенде. Для этого придется положить значение флага в Model и передать его на View как это показано ниже:
После чего использовать переданное значение для рендеринга того или иного HTML кода:
Виды feature switcher-ов
Описанный концепт использования feature switcher-ов — это лишь один возможный случай использования и такие feature switcher-ы называются release toggles. Всего выделяют 3 разных вида feature switcher-ов:
Проблемы использования feature toggle-ов
Поскольку я работаю на проекте, где активно используются feature toggle-ы, то кроме очевидных достоинств их использования я начал замечать и проблемы, связанные с ними:
Решения некоторых из описанных проблем
Помочь решить вышеописанные проблемы могут следующие действия:
Итоги
Feature switcher — очень простой и одновременно мощный механизм, позволяющий избегать монструозных коммитов, легко менять поведения приложения или собирать несколько разных приложений на одной кодовой базе, используя разную конфигурацию feature toggle-ов.
Однако, стоит также помнить, что этот паттерн разработки имеет некоторые недостатки, которые выливаются в трудночитаемый и трудно поддерживаемый код, поэтому следует избегать чрезмерного использования этого паттерна и периодически проводить документирование feature switcher-ов и их ревизию, чтобы удалять неиспользуемые и, как следствие, очищать проект от “мёртвого” кода.
Что такое feature toggle или как избавиться от мучительных мёржей и долгоживущих веток?
Проблема
Представьте, что циклы разработки вашей команды длятся по две недели, а реализация новой фичи потребует от команды 3 месяца разработки. На первый взгляд, есть две возможные схемы действий:
Использование feature switcher-ов для решения проблем
Такая проблема встречается в разработке довольно часто и есть изящное решение, позволяющее взять лучшее от описанных выше подходов — feature toggle или feature switcher.
По сути, feature switcher — это boolean флаг, который хранится в базе данных и содержит информацию о том, должна быть включена та или иная фича или нет. Значение этого флага может быть извлечено из базы данных по ключу. Удобство использования feature switcher-ов заключается в том, что они могут быть легко изменены бизнес-пользователем во время runtime через панель администратора без необходимости заново деплоить приложение.
Ниже приведен пример использования feature toggle на языке Java:
В примере выше configurationManager — это класс, позволяющий извлечь значение определенного feature switcher-а из базы данных по его ключу.
Также, при помощи feature switcher-ов, можно отображать/скрывать определенные элементы на фронтенде. Для этого придется положить значение флага в Model и передать его на View как это показано ниже:
После чего использовать переданное значение для рендеринга того или иного HTML кода:
Виды feature switcher-ов
Описанный концепт использования feature switcher-ов — это лишь один возможный случай использования и такие feature switcher-ы называются release toggles. Всего выделяют 3 разных вида feature switcher-ов:
Проблемы использования feature toggle-ов
Поскольку я работаю на проекте, где активно используются feature toggle-ы, то кроме очевидных достоинств их использования я начал замечать и проблемы, связанные с ними:
Решения некоторых из описанных проблем
Помочь решить вышеописанные проблемы могут следующие действия:
Итоги
Feature switcher — очень простой и одновременно мощный механизм, позволяющий избегать монструозных коммитов, легко менять поведения приложения или собирать несколько разных приложений на одной кодовой базе, используя разную конфигурацию feature toggle-ов.
Однако, стоит также помнить, что этот паттерн разработки имеет некоторые недостатки, которые выливаются в трудночитаемый и трудно поддерживаемый код, поэтому следует избегать чрезмерного использования этого паттерна и периодически проводить документирование feature switcher-ов и их ревизию, чтобы удалять неиспользуемые и, как следствие, очищать проект от “мёртвого” кода.
Что такое feature toggle или как избавиться от мучительных мёржей и долгоживущих веток?
Проблема
Представьте, что циклы разработки вашей команды длятся по две недели, а реализация новой фичи потребует от команды 3 месяца разработки. На первый взгляд, есть две возможные схемы действий:
Использование feature switcher-ов для решения проблем
Такая проблема встречается в разработке довольно часто и есть изящное решение, позволяющее взять лучшее от описанных выше подходов — feature toggle или feature switcher.
По сути, feature switcher — это boolean флаг, который хранится в базе данных и содержит информацию о том, должна быть включена та или иная фича или нет. Значение этого флага может быть извлечено из базы данных по ключу. Удобство использования feature switcher-ов заключается в том, что они могут быть легко изменены бизнес-пользователем во время runtime через панель администратора без необходимости заново деплоить приложение.
Ниже приведен пример использования feature toggle на языке Java:
В примере выше configurationManager — это класс, позволяющий извлечь значение определенного feature switcher-а из базы данных по его ключу.
Также, при помощи feature switcher-ов, можно отображать/скрывать определенные элементы на фронтенде. Для этого придется положить значение флага в Model и передать его на View как это показано ниже:
После чего использовать переданное значение для рендеринга того или иного HTML кода:
Виды feature switcher-ов
Описанный концепт использования feature switcher-ов — это лишь один возможный случай использования и такие feature switcher-ы называются release toggles. Всего выделяют 3 разных вида feature switcher-ов:
Проблемы использования feature toggle-ов
Поскольку я работаю на проекте, где активно используются feature toggle-ы, то кроме очевидных достоинств их использования я начал замечать и проблемы, связанные с ними:
Решения некоторых из описанных проблем
Помочь решить вышеописанные проблемы могут следующие действия:
Итоги
Feature switcher — очень простой и одновременно мощный механизм, позволяющий избегать монструозных коммитов, легко менять поведения приложения или собирать несколько разных приложений на одной кодовой базе, используя разную конфигурацию feature toggle-ов.
Однако, стоит также помнить, что этот паттерн разработки имеет некоторые недостатки, которые выливаются в трудночитаемый и трудно поддерживаемый код, поэтому следует избегать чрезмерного использования этого паттерна и периодически проводить документирование feature switcher-ов и их ревизию, чтобы удалять неиспользуемые и, как следствие, очищать проект от “мёртвого” кода.
Изолируем микросервисы с помощью Feature toggles в ASP.NET Core. Теория и подготовка
Привет, Хабр! Если вы работаете с микросервисами, то знаете, что они имеют свойство образовывать некоторую связанность. Хорошо, когда связи между микросервисами однонаправленные, но всё становится сложнее, если возникают циклические зависимости.
Такие зависимости приводят к сложностям развертывания, которые можно преодолеть по-разному — например, используя docker compose. Но на локальном компьютере обычно не возникает необходимости поднятия всей инфраструктуры, потому что разработчика для выполнения задачи обычно интересует какая-нибудь конкретная её часть. В этом случае пригодятся средства изоляции микросервисов.
Меня зовут Сергей Прохоров, я техлид бэкенд-разработки в Ak Bars Digital, и давайте вместе рассмотрим, как реализовать такую изоляцию на примере микросервиса веб-API ASP.NET Core. Метод изоляции основан на использовании feature toggles, или переключателей функциональности, о которых и пойдёт речь в двух частях статьи.
Зачем нужна изоляция микросервисов
Потребности в изоляции могут быть разными, вот лишь некоторые из них, которые встречаются в разработке и тестировании.
Для разработки
При онбординге нового сотрудника. В финтехе получение доступа к внешним зависимостям требуют написания служебных записок в службу безопасности (а это может быть не быстро), а в ряде случаев, к некоторым сервисам доступ вообще не может быть предоставлен — шифрование или каналы ГОСТ являются ярким тому примером.
При аудите или анализе микросервиса с целью выявления технического или архитектурного долга. Иногда логика не столь тривиальна и пройтись отладчиком сильно проще трассировки «в уме».
При необходимости оперативно вносить правки (bug fix) с возможностью отладки. Ускоряем отладку, не тратя время на подъем зависимых контуров и настройку взаимодействия с ними.
Чтобы постоянно не поддерживать актуальность долгоживущих веток предотвращать конфликты слияния. Здесь лучше посмотреть статью по ссылке — там эта информация хорошо объясняется.
Для тестирования
Интеграционное и регрессионное тестирование при разработке. Тестирование изолированного микросервиса позволяет разработчику, при внесении правок, самостоятельно и быстро обнаруживать возникающие дефекты в существующем коде.
Тестирование в рамках непрерывной интеграции (CI), которую выполняет агент сборки (build agent). Зачастую в его окружении нет, или даже не может быть, доступа ко всем зависимостям микросервиса, например из-за все тех же требований безопасности или инфраструктурных ограничений.
Тестирование сценариев взаимодействия с зависимостями. Так можно воспроизводить различные варианты без явных вызовов внешней зависимости, получая соответствующий результат используя внутреннюю логику заглушек.
При тестировании микросервиса, когда внешняя зависимость не имеет тестового контура, а использование промышленной версии в таких объемах неприемлемо. Примером могут служить внешние сервисы оплаты, в которые отправлять реальные деньги на нереальные суммы было бы крайне нежелательно.
При эксплуатации staging-контура заглушки нужны для целей тестирования. Сопряжение стейджинга с промышленными контурами чревато для целей тестирования, а сопряжение с тестовыми контурами зачастую неактуально. При этом исходная кодовая база должна быть идентичной production-контуру.
При нагрузочном тестировании, когда число запросов к внешним зависимостям лимитировано по частоте запросов или по их количеству.
Вместо изоляции в этих сценариях применяют различные инструменты, но в тех случаях, когда реализация посредством изоляции будет дешевле, нужно выбирать именно её.
Что такое feature toggles
Переключатели функциональности (feature toggles) или флаги функциональности (feature flags) — это переменные, которые используются внутри условных операторов.
Блоки внутри этих условных операторов могут быть включены или выключены в зависимости от значения переключателя функции. Это позволяет разработчикам контролировать поток выполнения своего программного обеспечения и обходить функциональность, которая не должна выполняться.
Переключатели можно использовать в следующих сценариях:
добавление новой функции;
улучшение существующей функции;
сокрытие или отключение функции;
Переключатели можно сохранить как свойство в файле конфигурации, в виде записи в базе данных или как запись во внешней службе функциональных флагов.
Канареечные релизы
Еще одно преимущество флагов функциональности — канареечные релизы.
Канареечный релиз позволяет разработчикам постепенно тестировать функции на небольшой группе пользователей. Если производительность функции по каким-то причинам не устраивает разработку или бизнес, ее можно откатить во избежание побочных эффектов.
Microsoft.FeatureManagement
Команды для подключения NuGet-пакетов в проекты с использованием dotnet CLI:
или используя диспетчер пакетов Visual Studio:
Поскольку Microsoft.FeatureManagement построен поверх системы конфигурации, он может управляться любым из самых разных поставщиков конфигурации. Это означает, что вы можете управлять функциями из файла appsettings.json, из переменных среды, из базы данных, или выбрать какой-то из большого количества готовых поставщиков или даже реализовать поставщика самостоятельно. Включение и отключение функции просто требует изменения значения в выбранном поставщике конфигурации.
Библиотека Microsoft.FeatureManagement.AspNetCore добавляет для ASP.NET функциональность, которая будет зависеть от заданного режима (включено/выключено):
фильтры действий для удаления действий контроллеров;
методы расширения для условной регистрации маршрутов, глобальные фильтры и промежуточное ПО;
вспомогательные функции тегов для условного скрытия разделов пользовательского интерфейса MVC.
Примеры настройки appsetings.json
Далее в этой и следующей части статьи я на примере разберу все аспекты работы с флагами функциональности.
Создание веб API ASP.NET Core приложения
Создадим приложение, на котором отработаем изоляцию микросервиса с использованием заглушки.
Создаём шаблонное приложение в Visual Studio
Шаг 1. Создаём пустое приложение Веб-API ASP.NET Core
Теперь можно запустить приложение и проверить его функциональность по умолчанию.
Мастер генерации приложения сформировал код контроллера, который генерирует случайный прогноз погоды.
Давайте сделаем так, чтобы приложение получало реальный прогноз с погодного сервиса, а сгенерированный код позже используем для изоляции — сможем переключаться на него с помощью флага функциональности.
Реализуем прогноз погоды
Для получения реальных данных прогноза погоды я выбрал сервис OpenWeather — он бесплатный, у него низкий порог входа и хорошая документация.
Класс конфигурации OpenWeather
Поиск идентификатора города
Чтобы легко жилось не только разработчикам, но и DevOps и QA-инженерам, вместе с ключами конфигурации стоит копировать в appsettings.json и комментарии. Например, так
Каждая библиотека, подключенная к проекту с помощью NuGet, может добавлять новые разделы в appsettings.json . Чтобы исключить случайные пересечения наименований разделов, мы размещаем разделы в качестве подразделов в App.
Для сопоставления значений из appsettings.json в экземпляры классов конфигурации OpenWeatherConfiguration осуществляется настройка в Startup.cs :
Реализация сервиса запросов
Далее объявляется интерфейс и класс реализации сервиса:
Интерфейс и класс реализации сервиса
Регистрация созданного сервиса и настройка фабрики HTTP-клиентов в Startup.cs :
Генерация и сопоставление моделей ответов
Генерация моделей ответа OpenWeather
Можно было бы воспользоваться документацией на сайте и написать модели ответа вручную, но можно пойти простым путём. Немного модифицировав исходный код текста получаем ответ от сервера в виде строки. После выполнения команды контекстного меню «Быстрая проверка» для переменной response, отображается её текущее значение:
Копируем значение в буфер обмена, а затем, остановив отладку и переставив курсор в конец файла, выполняем следующую команду:
Получилась такая структура проекта:
Такой подход к генерации моделей имеет недостатки: в зависимости от текущего значения в тексте могут быть применены целочисленные типы вместо типов с плавающей запятой, или вовсе не будут сгенерированы отдельные классы, если поля имеют значение null. Так что сверка с документацией всё же не будет лишней.
Подключение AutoMapper
Для сопоставления модели ответа OpenWeather и модели ответа контроллера используем NuGet-пакет AutoMapper.
Для такого простого примера это слишком, но в реальных проектах такой способ существенно упрощает разработку, поэтому используем именно его.
Команда подключения NuGet-пакета в проект с использованием dotnet CLI:
или используя диспетчер пакетов Visual Studio:
Класс настройки сопоставления моделей ответов:
Настройка AutoMapper в Startup.cs :
Изменения в контроллере
Как я уже упоминал, позже переиспользуем код, полученный при генерации решения по шаблону.
Чтобы не занимать буфер обмена, перетянем выделенный код контроллера на панель элементов, чтобы затем перетянуть его обратно в редактор при написании заглушки.
Теперь, когда прежний код отложен на панель элементов, код контроллера приводим к следующему виду:
Проверка функциональности приложения
На этом этапе у нас есть готовое приложение. Теперь его можно запустить и проверить боевую функциональность.
Что дальше?
Как видим, приложение работает, но это далеко не всё, что нужно сделать. Теперь нам нужна реализация заглушки, но её мы напишем во второй части статьи. Кроме этого сделаем экспериментальную конечную точку, функциональность которой можно включать или выключать, не останавливая работу приложения. А ещё разберёмся с экстренными ситуациями, которые могут случиться в реальной разработке, и поймём, как этого избежать с помощью флагов функциональности.
А пока спасибо за внимание, мы с коллегами из Ak Bars Digital готовы ответить на все вопросы в комментариях.