25 дек. 2025 г.·6 мин чтения

Управление флагами функций с помощью доменных политик и дат истечения

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

Управление флагами функций с помощью доменных политик и дат истечения

Почему флаги функций быстро становятся беспорядочными

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

Проблемы начинаются позже.

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

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

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

Потом временная логика закрепляется в архитектуре. Флаг, который когда‑то защищал миграцию, теперь сидит в биллинге, правах доступа или онбординге. Новая работа вынуждена учитывать оба пути. Тесты множатся. Небольшие изменения занимают больше времени, потому что никто не хочет трогать старую ветку, даже если никто уже не может объяснить, зачем она осталась.

Большинство команд не решают это дополнительными инструментами. Ещё одна панель не исправит привычку относиться к каждому флагу как к безобидной уловке. Чаще помогает нечто проще: написать, зачем флаг существует, кто его владелец, какое бизнес‑правило он поддерживает и когда он должен исчезнуть.

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

Как выглядит доменная политика

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

Политика должна быть на простом языке. Если продакт‑менеджер, инженер и руководитель поддержки не могут прочитать её и согласовать, что делает флаг, правило слишком расплывчатое. "Контролировать доступ к новому годовому плану для пользователей на рынке A до одобрения финансов" — ясно. "Поддерживать гибкие запуски" — нет.

Каждый флаг должен соответствовать одному бизнес‑правилу. Флаг для "новые клиенты получают обновлённый онбординг" — управляем. Флаг, который контролирует онбординг, прайсинг, текст писем и маршрутизацию в поддержку — будущая катастрофа. Как только один флаг несёт несколько идей, никто не понимает, когда его безопасно удалить.

Полезная политика обычно отвечает на четыре вопроса:

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

Владелец важнее, чем многие команды ожидают. "Инженерия" — не владелец. "Продукт" — тоже не владелец. Выберите конкретного человека. Этот человек решает, применимо ли правило всё ещё, завершён ли rollout и можно ли убрать флаг. Без названного владельца старые флаги остаются в коде, потому что все думают, что за это отвечает кто‑то другой.

План выхода должен существовать до релиза. Именно здесь команды обычно спотыкаются. Они быстро добавляют флаг, обещают убрать его позже и переходят дальше. Лучше заранее прописать выход: удалить флаг через 30 дней, после окончания A/B‑теста или когда юристы одобрят поток во всех регионах. Триггер может быть датой или конкретным событием, но он должен быть реальным.

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

Вот и вся идея. Держите правило маленьким, назначьте одного владельца и решите окончание до релиза. Флаги остаются временными, когда политика конкретна.

Привязывайте каждый флаг к реальному бизнес‑правилу

Флаг без бизнес‑правила быстро превращается в загадочный код. Через полгода никто не вспомнит, кто его просил, какой риск он контролировал и когда команда может его удалить.

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

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

Это звучит строго, но экономит время. Разработчик сможет понять, принадлежит ли флаг тесту прайсинга, региональному rollout или обещанию по контракту одному клиенту. Саппорт поймёт, намеренно ли такое поведение. Продукт поймёт, соответствует ли флаг реальному решению.

Названия помогают. Расплывчатый флаг вроде new_export_v2 скрывает суть. Более длинное имя типа enable_export_for_paid_eu_accounts_until_support_load_stays_below_2_percent некрасиво, но говорит правду. Видно, кому, где и по какому результату флаг остаётся.

Условие остановки самое важное. "Удалить после релиза" слабо, потому что релиз редко завершает обсуждение. "Удалить когда все платные EU‑аккаунты используют новый экспорт и обращения в поддержку ниже 2% в течение 30 дней" даёт команде реальный выход.

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

Храните причину рядом с названием флага там, где её видят и инженеры, и продукт. Короткого примечания достаточно: "Требуется для поэтапного rollout к немецким бизнес‑аккаунтам во время обновления НДС." Эта строка может сэкономить час переписки позже.

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

Как настроить новый флаг

Большинство флагов ломаются ещё до того, как их кто‑то пропишет. Команда добавляет быстрый переключатель для релиза, никто не назначает владельца, и через полгода временная проверка сидит в трёх сервисах и двух админ‑экранах.

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

Простой процесс настройки работает хорошо:

  1. Привяжите флаг к одному rollout, одному риску или одному бизнес‑ограничению. Если вы не можете объяснить цель в одном коротком предложении, сузьте её.
  2. Напишите бизнес‑правило, владельца и дату окончания рядом с названием флага. Владелец — это человек, который ответит: "Можем ли мы удалить это сегодня?"
  3. Держите одно место для правила в коде и одно в командной документации. В коде разместите проверку рядом с доменной логикой, а не разбросывайте её по хендлерам, заданиям и UI.
  4. Поставьте дату ревью в календарь до дня релиза. Дата в документе теряется, напоминание в календаре легче не заметить.
  5. Удаляйте флаг, когда сработает условие остановки. Если rollout достиг 100%, исключение клиента закончилось или тест провалился — удаляйте ветку и конфигурацию сразу.

Небольшой пример. Команда выпускает новый поток регистрации только для лидов с платной кампании. Правило должно прямо это сказать: показывать новый поток пользователям кампании до 30 апреля, пока поддержка отслеживает отток и неудачные регистрации. Теперь у команды есть понятная аудитория, владелец и конец.

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

Флаг без бизнес‑правила, владельца и даты окончания не должен попадать в релиз.

Простой пример из продуктовой команды

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

Представьте команду, которая продаёт ПО для управления проектами. Они хотят протестировать повышенную годовую цену, но только для компаний с 20–100 местами, покупающих онлайн без переговоров с менеджером по продажам. Корпоративные аккаунты остаются на контрактном прайсе. Очень маленькие команды сохраняют старые self‑serve планы.

До написания кода команда формулирует правило простым английским: "Применять тест только к Growth‑аккаунтам на self‑serve чек‑ауте." Это ограничивает область. Саппорт, биллинг и инженерия читают одно и то же правило, поэтому никто не добавит флаг в несвязанные потоки позже.

Они используют два флага и одно правило ревью. pricing_growth_v2_launch показывает новую цену этому сегменту. pricing_growth_v2_rollback возвращает тот же сегмент на старый путь, если ошибки биллинга или жалобы вырастут. Дата убийства — 30 дней после запуска, и команда прописывает её в задаче, реестре флагов и приглашении в календарь для ревью.

Старый код прайса пока остаётся, но лишь как кратковременная ветка в продуктовой логике. Новый флаг не решает, кто такой Growth‑аккаунт. Домен биллинга это уже знает. Флаг только решает, активна ли новая страница цены для клиентов, которые уже соответствуют правилу. Эта граница важна. Она предотвращает путаницу бизнес‑правил и флагов.

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

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

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

Ошибки, которые заставляют флаги оставаться

Управлять исключениями клиентов
Замените ad‑hoc переключатели ясными правилами для планов, доступа и исключений для клиентов.

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

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

Другая частая ошибка — один флаг для нескольких бизнес‑решений. В день добавления это может выглядеть аккуратно, но быстро портится. Один переключатель вдруг управляет rollout, прайсингом, доступом в поддержку и особым случаем для одного клиента. Тогда никто не удалит флаг без риска повредить что‑то ещё.

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

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

Самая тяжёлая к чистке путаница — вложенные проверки внутри доменной логики. Как только флаги зарываются в биллинг, права пользователя или поток заказов, удаление перестаёт быть маленькой задачей. Это превращается в рискованный рефакторинг, потому что код больше не показывает реальное бизнес‑правило в одном месте.

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

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

Если хотите, чтобы флаги уходили вовремя, задайте четыре прямых вопроса: кто владеет этим, какое одно правило он контролирует, когда он истекает и где задача по очистке? Если никто не ответит на них за минуту, флаг, вероятно, выполнил своё назначение.

Быстрые проверки вашего текущего списка флагов

Большинству команд не нужен новый инструмент сначала. Нужно 15 минут тишины, текущий список флагов и честный взгляд на то, что ещё заслуживает места в коде.

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

  • Попросите человека не из первоначального проекта объяснить бизнес‑правило за флагом в одном предложении. Если не может — флаг далёк от своей цели.
  • Проверьте, есть ли сегодня один человек‑владелец. Совместное владение обычно означает отсутствие владельца.
  • Сравните дату истечения с реальностью. Дата, которая уже прошла, — это пропущенное решение, а не пустая деталь.
  • Спросите, может ли команда удалить флаг в этом спринте. Если ответ всегда «может быть позже», флаг уже становится постоянным.
  • Посмотрите, где лежат проверки. Если один и тот же флаг встречается в бэкенде, UI, админке и скриптах поддержки, уборка будет только сложнее.

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

Что делать дальше

Навести порядок в продуктовой логике
Отделите временные флаги от реальных бизнес-правил с поддержкой Fractional CTO.

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

Начните с одной продуктовой области: регистрация, биллинг, онбординг или админ. Сгруппируйте активные флаги там. Затем отсортируйте по владельцам, чтобы у каждого флага был человек, который за него отвечает. Добавьте или подтвердите дату окончания для каждого, даже если первая дата — приблизительная. После этого удаляйте мёртвые флаги в первую очередь. Это быстро сокращает шум и делает оставшийся список легче для оценки.

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

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

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

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

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

Часто задаваемые вопросы

Когда следует создавать флаг функции?

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

Что должен включать каждый флаг?

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

Кто должен быть владельцем флага?

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

Сколько времени флаг должен оставаться в коде?

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

Должен ли один флаг контролировать несколько вещей?

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

Где лучше размещать логику флага?

Размещайте проверку близко к той доменной логике, которую она затрагивает, а не по всему приложению. Если биллинг владеет правилом, держите логику в биллинге и избегайте разброса одной и той же проверки по хендлерам, заданиям, UI‑коду и админским инструментам.

Как правильно называть флаг?

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

Как распознать устаревший флаг?

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

Как часто стоит пересматривать флаги?

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

Что нужно очистить при удалении флага?

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