Антон Степанов — Feature Toggling — в чем польза и как начать его применять

Антон Степанов — Feature Toggling — в чем польза и как начать его применять52:54

Информация о загрузке и деталях видео Антон Степанов — Feature Toggling — в чем польза и как начать его применять

Автор:

DotNext — конференция для .NET‑разработчиков

Дата публикации:

09.08.2024

Просмотров:

1.5K

Описание:

Спикер рассказывает, что такое Feature Toggling: какие проблемы он решает, какие у него есть плюсы и минусы. Разбираем несколько простых примеров из реального проекта.

Транскрибация видео

Спикер 5

Итак, здравствуйте.

Замечательное слово «здравствуйте», потому что, в отличие от автоматического «привет», желать здравия своим коллегам можно, сколько раз за день вы не встречались.

Здравствуйте, коллеги, которые здесь находятся в зале.

Приветствуем слушателей по ту сторону экрана.

Итак, о своем и наболевшем.

Напомню, на что мы потратили день сегодняшней конференции.

С утра нам звонил PM, требовал фичу, потом звонил, требовал коррекцию этой фичи.

И вот мы целый день протелепавшись с этим, собственно, мы нашли workflow, мы нашли fine-tuning для ролевой модели, для модели доступа.

Потом нам помогли пересмотреть это все, разобраться с Code Review.

И вот в конце пятницы прибегает счастливый Team Lead, говорит, ура, мы все выкатили, отчитались, все, итерация сдана, отлично.

Говорит, завтра проставляюсь.

Но с понедельника говорит, давайте новую фишу перейти.

Но мы же уже опытом умудренные, поэтому мы говорим, так, погоди, погоди, погоди, что ты там хочешь привить?

Ага.

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

Антон, расскажи как.

Спикер 3

Да, спасибо, всем привет.

Спасибо, что пришли на доклад, хотя он в конце дня, через 15 минут начинается нетворкинг.

Круто, спасибо.

Сегодня поговорим про фичетоглинг.

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

Вообще с чего стартануть.

Собственно, в чем его польза и как начать применять.

А поднимите руки, кто уже вообще использует фичетоглинг у себя?

Ага, 4, 5, 6.

Окей, круто.

Но не так много.

Интересно.

Поехали.

Пару слов обо мне.

Я работаю в компании Bandusoft.

Компания занимается продуктовой разработкой на заказ.

На рынке мы уже больше 11 лет.

И представлены наши разные клиенты, которые к нам приходили.

Если будет интересно, потом поотвечаю на вопросы, как мы разрабатываем.

Собственно, я, еще раз, Антон Степанов.

Больше 10 лет я пишу на Sharp, и больше 5 лет уже занимаюсь темлицкой деятельностью, руковожу командами.

Пробежимся по плану доклада.

Сначала разберем проблемы, из-за чего вообще мы начали использовать фичетоглинг.

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

Собственно, проблематика, почему вообще начали использовать у себя фичи-тогглинг, жили-сени-тужили и вообще почему.

Первая штука.

Межконфликты.

Стандартный кейс.

На проекте работает несколько команд.

И в параллели что-то там меняют.

И затрагивают, конечно же, одну кодовую базу.

Притом фичи большие.

Там одна фича, не знаю, месяц, вторая, пару месяцев.

И когда начинает этап вот этого слияния всего в деф или в мастер, у кого как,

то появляются какие-то лютые мерзконфликты на сотни файлов, на несколько дней работы.

И это очень больно.

Нас это немножко утомило.

Кстати, вот у кого-то есть проблемы?

Кто стал, не знаю, мерзать все это без конца?

Окей, есть парочку.

Это круто.

Следующая проблема, с которой мы столкнулись, она немножко перекликается с предыдущей.

Рефакторинг.

В чём кейс?

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

Фича 1, начинаем это всё рефатчить, и в это время стартует где-то фича 2.

И фича 2 тоже понимает, блин, всё плохо, и нам тоже нужен этот же рефакторинг, и у вас пути несколько.

Либо дождаться, когда фича 1 сольется в деф, но это неизвестно, когда будет, и это вашу фичу 2 будет стопорить.

Либо фичу 1, фичу 2 подмерзнуть, тоже какое-то такое спорное решение.

Собственно, вам нужен какой-то механизм спокойно переиспользовать код между фичами.

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

Мы писали просто конвенции, что рефакторинг в фичах нельзя делать.

Ну, типа, хотите делать рефакторинг, просто от девы отрефачьте, не меняя ничего, и слейте в дев, и тогда будет вам счастье.

Но фичи-флаги тоже в этом помогают.

Следующая проблемка.

Работаем все спокойно, работаем, пилим фича за фичой.

Вообще спокойно, все хорошо, все релизим.

Одну, вторую, третью запилили.

Уже все в проде давно работает, не знаю, там пару недель.

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

И ты такой приходишь за комп и думаешь, а как вообще это сделать-то?

Ну типа там все, там уже все, единый слепок, там уже ничего не оторвать.

То есть там ничего не ревертнуть.

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

Это тоже у нас такая проблемка была.

И еще одна проблемка последняя.

Мы часто приходим, когда клиентам, мы переписываем какие-то legacy системы, которые были написаны 20 лет назад гендиром на коленочке на Delphi, и никто не знает, как они работают.

Вообще никто.

И как должны работать, тоже никто не знает.

То есть просто оно работает, работает, не трогай.

А у нас задача эти системы переписать.

Но чтобы переписать, нам надо знать, как работали старые системы.

Окей, мы приходим, нам никто никаких ответов не может дать.

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

Ну, он стопудово будет.

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

Немного теории.

Собственно, что такое фичитоглинг вообще?

В чем его прикол?

Основная цель — отвязать релиз фич от заливки кода.

Поясню, как обычно происходит.

Как только мы нажали кнопочку в нашем CI-CD инструменте deploy, и код залился на прот, все, наш весь новый функционал, он сразу же начинает работать.

Но потом люди подумали, а может давайте, чтобы deploy был deploy, и он просто deploy, а непосредственно включение функционала мы будем...

Как-то отдельно делать.

Где-то будет какой-то тумблерочек, который скажет, а вот теперь этот функционал можно включать на проди.

Собственно, в этом концепция фичетоглинга.

Отвязать релиз фич от заливки кода.

Немножко терминов.

Фича – это какой-то наш новый функционал, который мы планируем реализовать.

Фичи флаг – это бинарная переменная.

То есть она либо включена, либо выключена.

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

И фильтр — это дополнительное какое-то правило вычисления нашего бинарного флага.

Более сложное, то есть не просто включено или выключено, а какие-то дополнительные условия.

По фильтрам сейчас чуть позже мы посмотрим.

Да, забыл сказать, что фича flag — это бинарная переменная, которая включена-выключена, с которой обязательно связан какой-то кусок кода, обычный if, который проверяет, собственно, если фича flag включен, то мы какой-то новый функционал делаем, если выключено, то, соответственно, не делаем или делаем что-то другое.

Так если это просто ивчик в каком-то коде, ну типа мы этих ивчиков, не знаю, за свою жизнь миллионы, миллиарды пишем, как тогда отличить фичи Toggle от обычной бизнес-логики?

В чем вообще отличие?

Спикер 4

Не знаю, у кого-нибудь есть идеи?

Окей.

О, давай.

А есть микрофон у нас?

Нету?

Спикер 8

Можно специально API для этого предусмотреть или же в каком-то специальном месте хранить эти таблы.

Спикер 3

Настройки приложения тоже можно хранить.

Спикер 8

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

Допустим, у вас есть список настроек, и у них есть категории.

Вот фичетоглы в отдельную категорию вынести.

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

Спикер 3

Я просто дополню.

То есть вот у меня опять задача какая-то, я пишу if.

Как я понимаю, что я на него буду создавать фичи flag, или это просто обычный if, как я и раньше всегда писал?

Спикер 8

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

Это, наверное, сам разработчик только может решить.

Спикер 3

А вот еще там далеко-далеко в уголке первым поднял.

Извини.

Спикер 2

Просто назвать явно, что это фича toggle.

Спикер 3

Ну, да, понятно.

Немножко другое хочу ответ.

Как бы тут правильного ответа нет, я сразу говорю, у меня просто интересные мнения.

Спикер 7

По диплою разные инстанции, одни с одной версией, другие с другими.

Спикер 3

Как вариант.

Но есть, правда, динамическое конфигурирование, которое тоже что-то похожее.

Спикер 5

Я потом тоже отвечу.

Спикер 6

На прошлом слайде упомянули фьючер-менеджер.

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

Спикер 3

Я больше вопрос именно логический.

Не погружайтесь туда, в код, а именно вот как мне надо понять, вот у меня какая-то фича прилетела.

И там какой-то уф-ифчик будет.

Как я пойму, надо вот это фичи-флаг все-таки или это обычная бизнес-логика?

Вот именно на уровне просто аналитика, не знаю.

Спикер 6

Как вариант в классе, но методы атрибутные есть.

Спикер 3

Ну, опять техническое.

Ну, сейчас, окей.

Давай вот последний раз.

Спикер 10

Ну, если можно безболезненно отключить и приложение будет работать, как раньше работало, то, наверное, фича.

Если же это отключать и это сломает всю логику, то это не фича.

Да, классная мысль.

Спасибо.

Спикер 5

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

И если меняет, то это точно фича.

Спикер 3

Классно.

Да, всем спасибо за ответы.

Я для себя такой критерий придумал.

Тоже, возможно, он неправильный, но как-то мне он помогает.

Короче, если вот это какое-то ветвление, мы неизвестно, когда будем его включать или выключать, когда оно будет работать, то это feature flag.

Если же это какая-то всегда постоянная логика и всегда это все известно, например, не знаю,

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

Вот такое правило я придумал.

Давайте теперь про типы фильтров.

Напомню, что такое фильтры.

Это какие-то дополнительные условия вычисления фичи флагов.

Собственно, самый простой фич-флаг — это его отсутствие.

То есть фича у нас либо включена, либо выключена.

Если включена, всем она показывается.

Если выключена, то никому не показывается.

Дальше.

Процент пользователей.

То есть мы показываем фичу только определенному проценту пользователей.

Это используется, чтобы постепенно выкатывать наш функционал.

То есть там на 5, на 10, на 20 пользователей и так поехали дальше.

Дальше тоже завязанный на пользователей таргетированный фильтр.

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

С атрибутами все понятно.

Возраст, пол, страна, девайс, хоть что, любой атрибут.

Под поведением имеется в виду, что я что-то сделал в приложении.

Я думаю, многие из вас видели такую кнопочку где-нибудь на сайте и попробовать новую версию сайта.

Это как раз поведение пользователя.

После нажатия на эту кнопку вы попадаете вот в этот таргетированный фильтр.

Обычно там есть еще вторая кнопка «Вернуться к старой», когда новый дизайн очень плох.

И вы, соответственно, из таргетированного фильтра исключаетесь, и фича вам перестает показываться.

Спикер 4

Временной интервал.

Спикер 3

Такая необычная штука, но это вот четыре стандартных типа фильтров.

Временной интервал.

Когда я хочу фичу показать в определенный момент времени, как-то не странно.

Например, с утра, потому что там

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

Или с утра там мало пользователей, поэтому мы там тестируем какую-то тоже новую версию сайта.

Собственно, какие плюсы дает использование фич-флагов?

Первое — это код-бранч-менеджмент, это решение как раз проблем мерч-конфликтов и рефакторинга.

В чем он заключается?

До этапа разработки фичи мы сразу добавляем фичи-флаг, который будет эту фичу закрывать.

И добавляем его в выключенном состоянии.

То есть по умолчанию наша новая фича, которую мы только еще собираемся разрабатывать, она выключена.

Что это нам позволяет сделать?

Мы можем теперь в Dev или в мастер, у кого как, мерзнуть наш код.

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

Он просто выключен и не работает.

Но так как мы теперь можем мерзнуться в любой момент времени, раз в день, trunk-based development, если кто-то использует, раз в день, в неделю и еще чаще, у нас теперь нет больших межконфликтов.

И так как мы опять-таки все смержили, мы можем переиспользовать код из разных фичей.

Очень классно.

Следующий плюс.

Тестирование в проде.

Да, мы можем тестировать это на миллиардов всяких стендов, тестовом, стейджевом, не знаю, на какие только есть.

Но самое крутое тестирование это, конечно же, в проде.

Потому что если мы что-то в проде потестируем, то оно так и будет работать в проде.

Потому что мы же в проде потестировали.

Оно не соврет.

Собственно, за счет чего мы можем потестировать в проде?

За счет того, что мы выкатываем, можем выкатить наш функционал, например, только на тестировщиков или на группу разработки.

Или на небольшой процент пользователей.

Я про это чуть дальше.

Собственно, флайтнинг — это как раз про поэтапную раскатку фичи.

То есть зачем нам рисковать и выкатывать фичу сразу на всех пользователей?

Мы можем по небольшим процентам ее выкатывать.

Начать с 5%.

Посмотреть, а наша инфраструктура-то выдерживает эту нагрузку новую?

А нет ли там сбоев, которые какие-то критичные?

То есть если есть, мы спокойно будем это как-то в фоне менять, ну и основную аудиторию никак не затронем.

И так постепенно, там 5, 10, 20, 50, 100, мы все выкатим и очень плавно, смотря как наша система себя ведет под этой новой фичой.

Следующее.

Собственно, это основная штука фичи тоггла.

Мгновенный переключатель.

То есть мы в любой момент времени просто щелчком какого-то тумблера можем функциональность определенную либо включить, либо выключить.

Нам не нужно тратить время на пересборку, передеплой нашего кода.

Буквально там какие-то доли секунд.

И на проде у нас меняется состав функционала.

Спикер 4

Следующий плюсик.

Спикер 3

Выборочная активация.

Это про таргетированные фильтры.

Мы можем не просто на какие-то группы активировать функционал, но, например,

добавить фич-флаг платной подписки, и если у чувака включена платная подписка, то ему, соответственно, какие-то новые фичи показываются.

То есть именно бизнесовый, разделить наш функционал по бизнесовым группам пользователей и его выкатывать, развивать.

Да, плюсов много, они крутые, но, конечно же, есть и минусы.

Если в целом все они связаны с какой-то сложностью, точнее с увеличением сложности.

Проектировать сложнее.

Потому что вам теперь перед стартом вообще начала разработки над фичой нужно подумать.

Мне нужен фич-флаг.

Окей.

А типа куда его добавить?

В какие сервисы там?

Как он будет работать?

На что повлияет?

Что будет, когда он будет включен?

И что будет, когда он не будет включен?

Все это нужно продумать еще до начала какой-то реализации фичи.

То есть какое-то дополнительное время, ресурсы потратить, чтобы все это продумать.

Код становится сложнее.

Тут все просто.

То есть условно у вас до этого был код линейный, а теперь у вас добавляются какие-то ивчики.

Ну и чем больше фичей, то соответственно там десятки, сотни каких-то ивов появляются.

Сложнее это все поддерживать, сложнее рефакторить.

Ну и вообще хоть как-то разобраться в этом коде.

Но опять-таки от количества фичей зависит.

То же самое.

Тестировать это сложнее, потому что опять-таки много появляется вариантов.

Типа 10 фич-флагов, а в какой комбинации-то их вообще тестировать?

Все со всеми, так это комбинаторный взрыв, и вот тестировщик делает такие глаза и, наверное, застрелится.

Или не все, а если не все, то тогда какой набор?

Мне понравилось, как советует Fowler.

Он советует делать два теста.

Первый, когда у нас все фичи вообще включены, чтобы проверить, что они друг другу не противоречат, и в целом система работает.

А второй, тестировать тот набор фичи флагов, который планируется, что будет работать в проде.

У нас планируется, что в штатном режиме система работает с шестью из десяти флагов.

Вот именно вот этот набор взять надо протестировать.

А все остальные комбинации не столь интересны, потому что они маловероятны.

Ну, понятно, что какие-то риски под этим есть, но в целом вот такой подход.

Документирование.

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

Задокументировать название фичи флага, на какую фичу он работает, как его включить, где найти вообще, какие системы затрагивает.

То есть все это нужно описать, чтобы в какой-то момент не было ответа, а я не знаю, как это работает и куда пойти, чтобы что-то там сделать.

Потому что если оно останется только в коде, а сервисов у вас много, десятки, сотни, то никто не сможет разобраться без какой-то единой документации.

Периодическая ревизия.

Самая интересная штука.

Фичи-флаги имеют свойство умирать.

И это нормально.

А умирают они потому что, например, поэтапная раскатка.

То есть мы начали раскатывать нашу фичу.

5, 10, 20, 100% пользователей, и все, фича теперь всегда включена, мы ее отладили, и все.

Но если она теперь всегда включена, то получается вторая ветка кода, которая была при выключенном флаге, теперь никогда не будет выполняться.

Появляется мусор в коде.

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

Короче, потратить время и силы, которые, по сути, какой-то бизнес ценности большой не несут.

Ну, точнее, прямой.

Понятно, что в долгосрочной перспективе тех долг, которые на все повлияют.

Вот такая неприятная штука.

Еще одна точка отказа.

Тут я немножко забежал вперед.

То есть у нас фичи-флаги могут конфигурироваться либо внутри одного приложения, либо у нас может быть какое-то внешнее решение,

куда все сервисы ходят и спрашивают там, а включена это фича или нет, скажи мне, пожалуйста.

И как раз, когда у вас есть какое-то внешнее решение, то получается вот еще одна система, за которой нужно мониторить, смотреть, что она доступна, что она не сломалась и так далее.

Теперь немножко про NetCore, как у нас фич-флаги в NetCore сделать.

Все очень просто.

Максов придумали и добавили в проектик фичи-менеджмент Aspen EdCore.

Его устанавливаем и в нашем стартапе просто подключаем этот фичи-менеджмент.

И также ниже регистрируем все фильтры, которые мы планируем использовать.

То есть в данном случае используется процентный фильтр, таргетированный, какой-то там мой фильтр кастомный.

Конфигурирование.

Конфигурирование фичи менеджмента основывается на стандартной системе конфигурирования неткора.

То есть это апсетинг JSON, который представлен на экране переменной окружения, командная строка «хочу».

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

Тут описаны вот сейчас две просто простые фичи.

Это фича новый дизайн, которая включена, и фича C, которая выключена.

Дальше, чтобы нам в коде...

Эти фичи использовать.

Для начала заведем класс с названиями этих фичей.

Потому что название фичей — это просто строки.

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

И вот просто заведем статичный класс с названиями наших фичей.

И с ним будем работать, чтобы не ошибиться.

Дальше.

Чтобы нам как раз проверить, включена фича или нет...

Мы просто в наш класс инжектим iFeatureManager, и самое нижнее выделение, у него есть метод из EnabledAsync, куда мы передаем название фичи.

Соответственно, если он вернет true, то мы какой-то функционал новой фичи делаем, если false, то работаем по-старому.

Также в стандартном вот этом пакете фич менеджмента есть классные атрибуты для неткора, для экшенов и контроллеров.

Это фичегейт.

То есть он сразу, ваш экшен либо контроллер, если фича включена, они будут работать.

Если она выключена, пользователь даже вообще не узнает, что они такие существуют.

Очень прикольно.

Также можно в зависимости от фичи подключать медалевары.

Тут нет примера, но такая возможность есть, если кому-то надо.

Интересная штука – консистентность.

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

Но что будет, если мы там в течение одного запроса несколько раз будем это проверять?

Все будет на самом деле плохо.

Стандартный фича-менеджер, он никакой консистентности не гарантирует.

Приведу пример.

Если у нас есть процентный фильтр показывать фичу 50% пользователей, и пользователь пошел в какой-то экшен, где эта фича проверяться будет два раза.

то с 50% вероятностью iFitch Manager ему либо true, либо false даст.

Ну и ваш код, скорее всего, вообще очень неожиданно будет работать.

Для этого есть iFitch Manager Snapshot.

Он гарантирует, что значение вашей фичи вычисленное, оно будет консистентно в рамках запроса.

Окей.

Но обычно у нас пользователь делает много запросов.

И то есть мы ожидаем, что все последующие запросы тоже будут как бы, если фича была включена, то и для всех последующих она должна быть включена.

Для этого уже нужен iSessionManager.

Это из фич-менеджмента специальный менеджер.

То есть он позволяет вам в рамках сессии уже хранить где-то значение фичей.

Это может быть база, куки, не знаю, что придумаете.

Но у этого менеджера есть тоже подводные камни.

То есть а что нам кыш игровать?

Если какая-то процентный фильтр, ну окей, вроде сработает.

Если же это временной фильтр, то уже появляются проблемы.

Допустим, не знаю, у нас фильтр, что с 8 до 10 фича работает, а пользователь пришел в 7 утра, зашел, у него вычислилось значение, что фича еще не активна, и стешен менеджер это запомнил.

Наступает 8 часов,

А ничего не происходит, потому что у него закошировалось значение.

То есть нужно понимать, когда его можно использовать, а когда есть какие-то риски.

Ну или не использовать, например, временные фильтры.

Дальше.

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

Например, сейчас создадим фильтр, который будет показывать фичу пользователям в зависимости от их возраста.

Точнее, чтобы они были старше какого-то возраста.

Для начала создадим класс настроек этого фильтра.

Очевидно, что у нас будет одно поле, это минимальный возраст, начиная с которого мы показываем фичу.

Дальше создаем сам фильтр.

Все, что надо, это занаследоваться от iFeature фильтра.

там всякие пропущенные всякие кторы, и реализовать метод evaluateAsync.

То есть на примере мы из контекста, из клеймов берем возраст пользователя и потом сравниваем возраст пользователя с настройками нашего фильтра.

Соответственно, если возраст больше либо равен, то фича будет показываться.

И еще сверху вот у этого класса есть атрибут фильтра alias.

Этот атрибутик говорит, как будет называться секция конфигурирования этого фичи фильтра в нашей конфигурации.

Сейчас дальше покажу, будет понятнее.

Просто надо запомнить, что тут age.

Собственно, как выглядит конфигурация вот этого нашего нового фильтра.

У нас есть какая-то фича «старые люди».

И в секции enabled for, это тоже стандартная секция фичи менеджмента, в которой мы описываем все наши фильтры, которые надо применять для этой фичи.

Как раз вот name age, он поймет, что это тот наш фильтр по атрибуту.

И описываем параметры, минимум, который у нас был 70 лет.

Собственно, и все.

Ну и в самом начале регистрируем это в стартапе.

С фильтрами понятно.

Пойдем дальше.

Окей, мы таки начинаем развиваться, и нам стандартной системы конфигурирования NetCore не хватает.

Мы хотим чего-то больше.

Например, мы хотим значение фич флагов хранить в базе.

Окей, мы можем просто расширить систему конфигурации NetCore.

Для этого пишем extension для configuration провайдера, который просто возвращает нам наш database configuration source.

Ну и передаем ему строку подключения для базы.

Дальше.

DatabaseConfigurationSource, все, что он делает, он просто билдит DatabaseConfigurationProvider, промежуточный класс.

И вот уже в DatabaseConfigurationProvider вся логика реализована.

То есть нам нужно занаследоваться от ConfigurationProvider и переопределить метод, точнее реализовать метод load.

в котором мы как раз каким-то образом должны подтянуть нужные нам настройки из базы.

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

И, соответственно, просто записываете в Data и релодите, говорите всем снаружи, кто мониторит систему конфигурирования, что что-то в системе поменялось, подтяни настройки.

В принципе, имеет место на жизнь, но единственное, мало чего можно через это реализовать.

Например, HTTP-запросы уже не такие классные будут.

А кто какие минусы в таком подходе расширения?

Конфигурирование Netcore может сказать просто на уровне идей.

Или может что-то уже расширял, видимо уже расширял.

А сейчас микрофон где-то... Вот, да.

Спикер 2

Одна из мыслей, которая возникла, если у нас несколько инстансов приложения, как синхронизировать конфигурации между ними?

Спикер 3

Все плохо будет.

В смысле, когда уже с базой или нет?

Спикер 2

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

Спикер 3

А, то, что в базе изменились?

Спикер 2

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

То есть здесь нужно четким механизмом наблюдаться как минимум.

Спикер 3

Да, это хороший минус.

Спикер 4

Еще у Коки идея есть.

Спикер 1

Да, у меня быстрый минус, а саму connection string тоже нужно где-то хранить, тоже в конфиге, да?

Спикер 3

Ну да.

Спикер 1

Если у вас есть провайдер, которому нужна конфигурация, ее тоже откуда-то нужно взять, видимо, захардкодить, может, еще как-то.

Спикер 3

Спасибо.

Еще?

Вот, еще есть.

Спикер 9

У нас есть немаленькая вероятность, что источник этих данных будет недоступен.

Нужно иметь либо какой-то кэш, либо еще что-то.

Спикер 3

Да, классная штука.

Ну да, вообще тогда все понятно.

Да, все классно, и вы минусы назвали, и я еще один назову.

Вся система конфигурирования NetCore работает, к сожалению, синхронно.

Там нет синхроничной никакой вообще.

Она синхронно работает.

И поэтому, если мы что-то хотим

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

Все, что нужно, это занаследоваться от iFitchDefinitionProvider,

и реализовать метод getFeatureDefinitionAsync.

Ну, там больше методов, я просто один для примера.

Тут он уже полностью асинхронный.

Мы любые штуки можем писать, awaitить.

В данном примере, то есть мы создаем, по HTTP идем в какой-то наш, не знаю, in-house service, in-house feature service, получаем значение фичей и их отдаем.

Решение уже получше,

И, в принципе, с ним можно жить.

То есть где-то уже централизованно фичи будут храниться.

И чтобы он заработал, нам нужно перед ad-fiche-management обязательно его, наш фичи-дефинишн-провайдер зарегать.

Иначе ничего работать не будет.

Потому что там прямо внутри ad-fiche-management проверяется, типа, если уже что-то зареган, какой-то фичи-дефинишн-провайдер, то стандартный не регай.

Самое интересное.

Вспомним, что нам надо как-то ревизить наши фичи-флаги.

А чтобы их как-то ревизить, ну типа руками можно, конечно, но неохота.

И в идеале нам нужны метрики, которые показывают, какие фичи-флаги используются.

А типа они как-то перещелкиваются или они всегда в одном состоянии.

А в идеале, чтобы вообще алерты были.

И, к сожалению, стандартный пакет фич-менеджмента никаких метрик не предоставляет.

Ну и типа как-то там даже подсунуться нельзя.

Его с 2019 года у них висит ишью, заходил неделю назад проверить, ну типа ничего не сдвинулось.

Да, немножко неприятная штука.

Но, конечно же, когда что-то не подходит, можно использовать какое-то внешнее хранилище флагов.

Вы можете сами начать пилить какое-то свое in-house решение, либо можно использовать, не знаю, их там кучи всяких разных, готовых, то есть это прям, они долго к этому шли, там вот самые, наверное, популярные это Unleash, LaunchDarkly, то есть они прям заточены чисто на метрике.

Они круто умеют их создавать, круто отдают метрики, аналитику, лерты и все в этом духе.

Единственное,

Про хранилище недоступного, да, мы уже разговаривали.

Единственное, почему-то все они предоставляют свой уникальный SDK.

Ну и типа, ну понятно, что они хоть как предоставляют свой уникальный SDK, но типа там прям разные методы, по-разному все заводится, непонятно нафига.

Но вот пару лет появилась open-feature-инициатива, это как open-telemetry, open-tracing, где люди такие, блин, реально все по-разному, нафиг мы все по-разному делаем, давайте все как-то в едином стиле делать, чтобы люди не мучились.

И в случае чего легко могли один feature-провайдер заменить на другой.

Проект развивается, проект классный, жаль, что...

Feature Management у Microsoft здесь нет, потому что там Open Feature немножко пошире стандарт.

Сейчас есть как раз уже провайдеры, Open Feature провайдеры для LaunchDarkly, для Unleash, и еще там много есть.

Прикольная штука, мне очень понравилась.

И то есть если будете какое-то внешнее как раз хранилище использовать, лучше заходите через провайдер, через Open Feature Provider для конкретного вашего решения, чтобы у вас код не зависел.

Дальше.

Наконец-то мы подобрались к небольшим примерчикам.

Собственно, чем мы... Проект будет про документы оборот.

Обрабатываем документы...

Как ни странно, да, обрабатываем документы.

Обработка документов.

Короче, что там такое?

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

И есть старая система, это сверху Legacy десктопные обработчики, там какой-то Legacy пост-обработчик.

И нам нужно было это все перевести как-то в облака, ну и вообще код переписать, чтобы понимать, как он работает.

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

Поэтому мы понимали, что точно то, что мы там раскопали, мы могли недораскопать, и что-то пойдет не так.

Начали думать, а как нам сделать так, чтобы максимально безопасно зарелизиться.

Окей, у нас есть там много типов документов, и мы решили добавить feature flag на каждый тип документа.

То есть feature flag там включен, этот тип документов идет по новой системе.

Если выключен, то мы его в середине пути перенаправляем в старую систему.

Собственно, что это нам позволило сделать?

Ну, во-первых, зарелизиться.

И когда мы зарелизились, были действительно проблемы, что мы там что-то не учли.

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

То есть мы релизились максимально спокойно.

Для команды это очень важно.

Собственно, тогда мы еще не знали про фичи-менеджмент.

Это были просто настроечки прямо в сервисе, в конфигурации.

Кстати, по большому секрету, вот если прям простые фичи-флаги,

Ну типа вам не надо ничего заводить, это может быть просто настройки в конфиге.

Это то же самое.

Это просто люди уж потом накрутили.

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

То есть не было множества сервисов, которые на это завязаны.

И заменяли мы просто.

У нас был тогда партейнер, мы заходили в партейнер, просто меняли переменное окружение, сохраняли, контейнер рестартил в течение 10-20 секунд, и все работало как надо.

Следующий пример.

Хранение файлов в S3 вместо базы.

S3 — это облачное хранилище файлов.

Вот так выглядела архитектура, когда у нас появилась задачка.

Какая задачка?

Была база.

Старая база, плохая или хорошая, в которую сваливались бинарии всех файлов, которые только можно.

И прикол в том, что ограничение по размеру файла было в 250 мегабайт.

Ну, а файлы летят там десятками тысяч.

База MS SQL.

Конечно же, эта база, я не знаю, спустя...

Ну, конечно, не полчаса работы, но, короче, очень быстро ей становилось плохо.

Там специально были настроены какие-то архивации, чтобы хоть как-то ее там разгружать.

И на очередном планировании появилась задачка, давайте-ка уже мы файлы все-таки не в базе будем хранить, а вот в облачном хранилище.

Окей.

Но прикол в том, что на эту базу завязаны и старые сервисы, и новые.

По новым вопросов нет.

Мы их условно знаем, мы их написали.

Понятен срок, когда мы перейдем на S3.

Понятно, сколько это по ресурсам займет.

А вот с Legacy и сервисами было непонятно.

То есть вообще непонятно было, когда это сделают и сделают ли вообще.

Кто это будет делать.

Но все равно дали старт, что надо работы начинать.

Мы понимаем, что если мы сейчас просто перейдем на S3, то потеряется обратная совместимость с Legacy системами и будет все плохо.

Так как мы не знали, когда Legacy системы перейдут на S3, то мы решили, что нам нужно это сразу заложиться и сделали так.

Все новые сервисы мы перевели на S3, то есть они по умолчанию сохраняют все в S3 как целевое решение.

Но добавили флажок.

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

Ну, чтобы с этим могли работать там Legacy системы.

Если выключен, соответственно, не сохраняй.

Это позволило нам зарелизиться.

Legacy системы до сих пор так и не перешли на S3.

Когда перейдут, неизвестно.

Но мы надеемся и верим, что когда-то это произойдет.

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

Да, пару советов, наверное.

Когда мы добавляем какой-то фичи-флаг, вот опишите все в карточке максимально подробно.

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

Описать, собственно, как он будет работать, когда он включен и когда выключен.

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

И в карточке на удаление как раз указывайте примерную дату истечения удаления, либо точную, если она вам известна.

Список сервисов, которые надо почистить.

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

И вам говорили, и даже карточки, чтобы автоматом создавались.

Спикер 4

Вообще круто.

Логирование фичей.

Спикер 3

Окей, мы начали использовать фич-флаги в Prodi, все круто, кайфуем.

И тут на Prodi что-то случается.

Что-то упало.

Приходят к вам, и первый вопрос, скорее всего, у вас будет, а в каком состоянии вообще сервис-то был там?

Сколько и скольки фичей, где было включено?

Потому что без этой информации разбираться, ну, это будет очень больно.

То есть вам нужно знать состояние.

Для этого логируете как раз значение фич-флагов.

Логируете при старте, при стопе, при смене.

Если у вас есть трассировки, круто, логируете и в трассировках.

Если нет трассировок, логируете и в логах.

Это вам сильно потом поможет при отладке инцидентов.

Следующая штука — схема базы данных.

Что делать, если фича просто какой-то новый функционал добавляет?

Вопросов нет, просто делаем, все круто и легко.

Но проблемки начинаются, когда у нас фича затрагивает как-то базу.

Она удаляет, не дай бог, старый какой-то существующий столбец или переименовывает.

И типа что делать?

У вас же система должна работать как с включенным фичи-флагом, так и с выключенным.

Обычно мы используем поэтапные миграции.

То есть на первом этапе, когда мы можем включать-выключать, нам нужно схему базы сделать таким образом, чтобы она поддерживала две фичи.

То есть это какие-то nullable поля, которые по идее должны быть не nullable.

Это какие-то записи в старые колонки для обратной совместимости.

И обязательно должен быть как раз вот второй этап.

Можно его записать как раз вот в карточку на удаление фичи-флага.

Это когда мы уже поняли, что фичи-флаг уже навсегда включен и уже не изменится.

И мы должны прийти и удалить обратную совместимость.

То есть как раз сделать неналабл полианалаблами, удалить вот эти какие-то легоси колонки и так далее.

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

У нас, например, атрибутом, что типа не запускайся, пока я тебе явно не скажу.

Собственно...

Фичтоглин – крутая практика, помогает решить ряд вопросов.

В нашем случае мы с мерзконфликтами и с рефакторингом поборолись с тем, что мы все часто мерзим.

потому что все закрыто флагами и не рушит прот.

И с отсутствием документации к Legacy систем, опять-таки, это вот мы то, что мгновенно можем функционал переключать туда-сюда.

То есть feature toggling решает какие-то наборы конкретных проблем.

Если у вас есть такие проблемы, то вы можете попробовать feature toggling.

А как его попробовать?

Я бы рекомендовал потихонечку начать, ну если вы вообще не использовали, начните со стандартного пакета Microsoft SQL, Pitch Management.

Мы его используем, там, не знаю, тестово в одном сервисе, во втором, и когда понимаем там, что в нем чего-то не хватает, ну пытаемся в нем допилить.

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

Да, начните свой путь с фич-флагами, я от него кайфую.

Моя почта, телеграм, и буду рад, если вы оставите обратную связь по QR-коду.

Спасибо.

Спикер 5

Ну, Антон, ты нам дал последнюю линию обороны против ошибок аналитиков.

Спасибо большое.

Коллеги, собственно, пишем.

По результатам конференции будут еще какие-то артефакты, безусловно.

Например, точно будут исследования дополнительные по Ардуине, будут дополнительные метапы и точно будет подкаст по метрикам.

И мы расскажем об опыте использования фишер-флагов.

так или иначе, в рамках каких-то мероприятий .NET, собственно, комьюнити.

Поэтому спасибо огромное.

Спасибо всем, кто сегодня выступал.

И, Антон, еще раз спасибо тебе.

Спасибо.