awesome-everything EN
↑ Обратно к восхождению

Инженерная практика

Feature flags: чтение кода и targeting

Суть Читаем реальный код вычисления флага и правило targeting, предсказываем поведение или баг и выбираем самую рычажную правку, которую senior делает первой.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

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

Цель

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

Сниппет 1 — проверка раскатки

function inRollout(flag, user) {
  // раскатка 25%: разыгрываем свежее случайное число на каждый вызов
  return Math.random() * 100 < flag.rolloutPercent;
}

if (inRollout(newCheckout, user)) {
  return renderNewCheckout(user);
}
return renderOldCheckout(user);
Викторина

Раскатка на 25% использует эту проверку. Что ломается в проде и в чём правка?

Сниппет 2 — путь kill switch

async function chargeCard(order) {
  const enabled = await flags.evaluate("payments-enabled", order.user);
  if (!enabled) {
    throw new Error("payments disabled by kill-switch");
  }
  return gateway.charge(order);
}

// flags.evaluate бросает исключение, если сервис флагов недоступен
Викторина

Здесь kill switch обёрнут вокруг платежей. В чём продовый риск и какова senior-правка?

Сниппет 3 — правило targeting

flag: new-dashboard
rules:
  - if: user.plan == "enterprise"
    serve: on
  - if: user.betaOptIn == true
    serve: on
  - rollout:
      percent: 10
      stickyBy: user.id
default: off
Викторина

Enterprise-пользователь, который вдобавок подписался на бету, открывает дашборд. Какое правило решает его вариант и на какое общее свойство опирается этот конфиг?

Сниппет 4 — застойный флаг в коде

// добавлено 2023-02 для релиза checkout-v2, доведено до 100% в 2023-03
if (flags.isEnabled("checkout-v2")) {
  return renderCheckoutV2(cart);
} else {
  return renderCheckoutV1(cart);   // V1 больше не поддерживается
}
Викторина

Прошёл год; checkout-v2 отдаёт on всем с 2023-03, а V1 не поддерживается. Какое действие правильно и почему?

Итог

Каждое ревью флагов читается одинаково: проверка раскатки обязана хешировать стабильный ключ в фиксированную корзину, иначе она мигает; kill switch обязан вычисляться локально с безопасным дефолтом, иначе сервис флагов становится жёсткой зависимостью, роняющей ваш горячий путь; правила targeting чувствительны к порядку и первое совпадение замыкает вычисление, так что порядок правил — это приоритет; а release-флаг на 100% с неподдерживаемой второй веткой — это flag debt на удаление, а не конфиг на сохранение. Прочитать путь вычисления, починить структуру, затем пере-ревьюить.

Продолжить восхождение ↑Feature flags: выкатить тёмным, раскатать и вывести из эксплуатации
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.