Бесплатный интерактивный курс · aicoding.space

Архитектурный шлюз: решение с названной ценой

Практический курс по пакету @dzhechkov/skills-book-fundamental-software-architecture. Вместе с Никой ты поставишь шлюз архитектурных решений, научишься читать шестичастную записку решения, выбирать одно routing family из шести, отдавать чужие артефакты их владельцам, просеивать драйверы, считать цену распределения, находить границу архитектурного кванта, закрывать три окна потери сообщений, ставить исполняемую функцию пригодности и вести риск-шторм — а в конце увидишь, где сам пакет честно молчит.

Содержание курса

1. Шлюз, а не энциклопедия стилей

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

Ключевая мысль: gateway архитектурных решений

Ника ведёт платёжную команду в сервисе доставки. В понедельник её позвали на встречу, где вопрос звучал коротко: «Режем монолит заказов на сервисы или пока нет?» — и все посмотрели на неё. Ника открыла браузер, набрала «microservices vs monolith» и через двадцать минут закрыла: двенадцать статей, двенадцать правильных ответов, ни одной цены.

Пакет @dzhechkov/skills-book-fundamental-software-architecture сделан ровно для этой минуты. Это gateway архитектурных решений — один вход, который не пересказывает стили подряд, а делает три вещи по очереди: определяет, какой именно вопрос ты решаешь, открывает ровно один протокол под него и возвращает выбор с названной ценой.

«Gateway» здесь термин самого пакета, а не украшение. Шлюз ничего не рисует и не пишет ADR сам — он выбирает маршрут и передаёт оформление профильному навыку.

Что лежит внутри:

  • 26 протоколов-reference в каталоге fundamental-software-architecture-guide/references/;
  • 6 семейств маршрутизации — по одному на тип архитектурного вопроса;
  • лексический срез на 315 KU для глубокого поиска по книге-источнику.

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

Ссылки на сам пакет: страница на npm · исходники и README на GitHub.

2. Установка и первый вопрос вслух

Одна команда — и дальше ты разговариваешь с агентом обычными словами.

Ключевая мысль: установка пакета командой dz install

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

В Codex:

dz install @dzhechkov/skills-book-fundamental-software-architecture --target codex

Тот же канонический навык в Claude Code — меняется только цель установки:

dz install @dzhechkov/skills-book-fundamental-software-architecture --target claude-code

Из монорепозитория пакет можно поставить и по пути — это поддерживаемый способ для дерева разработки:
dz install ./packages/skills-book-fundamental-software-architecture --target codex.

Дальше команд заучивать не надо. Ника просто пишет агенту:

> «Используй fundamental-software-architecture-guide для выбора архитектуры заказов; покажи контекст, драйверы, принятый компромисс и как его проверить.»

Шлюз выбирает одно доминирующее семейство и передаёт конкретную работу навыку-владельцу, если такой есть. Одно исключение стоит запомнить сразу: семейство архитектурной коммуникации намеренно оставлено только справочным — оно не срабатывает автоматически, а передаёт работу навыкам по C4 и документации.

Проверка, что всё встало: попроси агента назвать шесть семейств маршрутизации. Если он называет их своими словами из книги вообще — навык не подключился; если называет fsa-family-* — подключился.

3. Анатомия архитектурной записки

Шесть частей ответа, без которых это не решение, а мнение.

Ключевая мысль: принятая отрицательная сторона решения

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

Записка идёт строго по порядку:

  1. контекст и требуемые свойства;
  2. выбранный протокол решения;
  3. проверенные варианты и наблюдаемые данные;
  4. рекомендуемый вариант и его отрицательные последствия;
  5. риск, постусловие проверки и момент пересмотра;
  6. следующий профильный навык для оформления или реализации.

Машиночитаемая половина того же ответа — поля decision, dominant_family, accepted_downside, verification_condition, reconsideration_trigger и handoff.

Несущий пункт здесь четвёртый. Принятая отрицательная сторона решения — это не оговорка вежливости, а признак того, что выбор действительно сделан. Ника проверяет любой архитектурный ответ одним вопросом: «чем мы за это платим?» Если ответить нечем, перед ней список достоинств, и решение ещё не принято.

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

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

4. Шесть семейств: с какого вопроса ты начинаешь

Внешний контракт шлюза: доминирующий вопрос выбирает ровно одно семейство.

Ключевая мысль: ровно одно routing family

Ника попробовала спросить обо всём сразу: и про границы, и про события, и про правило для сборки. Ответ получился широкий и бесполезный. Шлюз устроен иначе намеренно: выбирается ровно одно routing family — по тому вопросу, который доминирует прямо сейчас.

Шесть семейств и их главные вопросы:

  • fsa-family-choice-and-fit — что выбираем, какую цену принимаем, подходит ли стиль и среда, когда пересматриваем;
  • fsa-family-boundaries-and-coupling — где проходят границы ответственности, связанности, данных и независимого изменения;
  • fsa-family-distributed-interaction — как распределённые части обмениваются событиями и восстанавливаются после сбоя;
  • fsa-family-guardrails-and-risk — как сделать архитектурное правило или риск проверяемым;
  • fsa-family-architecture-communication — какую смысловую модель показать конкретной аудитории;
  • fsa-family-organization-and-participation — кто и как участвует в архитектурном решении.

Вторым шагом внутри выбранного семейства открывается один reference — из 26. Не два и не три: несколько протоколов сразу раздувают контекст, а владелец решения теряется.

Как разрешать пограничные случаи, если вопросов честно два. Начинай с более раннего необратимого решения. Цену распределения (протокол 08) проверяй до границ микросервисов (19). Семантику payload (14) определяй до механизма доставки (15) — но если проблема уже сформулирована как потеря или порядок сообщений, начинай с доставки. И архитектурное решение всегда принимается до создания ADR, C4 или кода.

Следующий маршрут разрешён только как явно названный follow-up, а не как «заодно посмотрим ещё вот это».

5. Сначала отдай чужое

Проверка границ до выбора протокола: половина запросов вообще не к этому навыку.

Ключевая мысль: чужой артефакт передаётся профильному навыку

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

Ника выучила таблицу границ за один вечер:

  • записать принятое решение как ADR → architecture-decision-records или capture-adr;
  • провести полный путь фичи до ADR → feature-adr;
  • нарисовать или проверить C4 → c4-architecture;
  • спроектировать REST/OpenAPI → api-design; GraphQL-схему → graphql-schema;
  • схема, DDL, индекс, миграция → database-review, database-migration или профильный ddia-*;
  • надёжность, масштабируемость, SLO и базовые p95/p99 → ddia-reliability-scalability-foundations;
  • ETL или потоковый конвейер данных → data-pipeline;
  • OTel, дашборд, алерты → observability; хаос-эксперимент → qe-chaos-resilience;
  • инцидент, безопасность, риск коммита → incident-response, security-audit, risk-assessment.

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

Обратная ошибка тоже реальна: слово «архитектура» в запросе само по себе ничего не решает. Просьба «нарисуй архитектуру нашей системы в Mermaid» — это заказ на диаграмму, и она уходит в c4-architecture, а не сюда.

Ника проверяет себя одним вопросом: «мне нужен ВЫБОР или мне нужен АРТЕФАКТ?» Артефакт — это к владельцу.

6. Сито драйверов: «быстро» — это не требование

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

Ключевая мысль: структурный фильтр архитектурных драйверов

Нике принесли требования: «быстро, надёжно, гибко и чтобы масштабировалось». Протокол 02 существует ровно против такой формулировки — это структурный фильтр архитектурных драйверов.

Фильтр работает так:

  1. Собери три входа — цели бизнеса, явные требования и неявные особенности предметной области. Спрашивай владельцев, а не только документ.
  2. Отдели поведение от способа его обеспечения. Кандидат остаётся архитектурным, только если требует структурной поддержки и его отсутствие всерьёз угрожает системе.
  3. Разложи составные слова. «Быстро вывести на рынок» может распадаться на изменяемость, тестируемость и развёртываемость — но это направление анализа, а не постоянное соответствие.
  4. Договорись о словаре. Для спорного термина зафиксируй смысл, границы и отличие от соседнего понятия — и используй одни и те же определения в требованиях и в решениях.
  5. Уточни сценарий измерения. Для доступности — период работы и простоя; для восстановления — срок возврата и резервирование; для производительности — отклик, стресс, пик и частота.
  6. Не прячь профиль нагрузки за средним. К вопросу «сколько?» добавь «когда?», «за какой интервал?» и «насколько неравномерно?». Устойчивый рост одновременной нагрузки и короткий всплеск — это разные проверки.
  7. Спроси, хватает ли практик кода. Поднимай свойство до уровня топологии или протокола, только если локальные меры цели не достигают.

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

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

7. Наименее плохой вариант

Веса назначают до подсчёта, а вариант без цены — признак недоделанного анализа.

Ключевая мысль: наименее плохой компромисс

У Ники на столе три варианта, и ни один не хорош. Протокол 01 говорит: так и должно быть. Архитектура выбирает не лучший вариант, а наименее плохой компромисс — и это не пессимизм, а рабочее определение.

Порядок такой:

  1. Оцени масштаб решения — горизонт жизни, цену замены, радиус последствий. Один признак сам по себе ничего не доказывает; архитектурным выбор делает сочетание.
  2. Сними контекст — цели, среда, сроки, бюджет, навыки, устройство команды, техническая культура. Вывод из другого проекта без повторной проверки этих условий не переносится.
  3. Назови настоящие альтернативы — не только любимый вариант и его противоположность, но и полюса, промежуточные и гибридные положения.
  4. Назначь критерии и веса ДО подсчёта. Число плюсов не заменяет веса, согласованные с целями.
  5. Проверь спорное утверждение экспериментом. Один сценарий, близкий к деловой задаче, одинаковые критерии, сопоставимое окружение. POC подтверждает сценарий, а не всю систему.
  6. Выбери приемлемые потери. При близких результатах предпочитай более изменяемый вариант.
  7. Сохрани контекст решения и триггер пересмотра.

Вот правило, ради которого Ника и переписала свой первый анализ: если у варианта видны только достоинства, анализ не закончен — ищи причинно связанную цену дальше. Ноль недостатков означает не идеальный вариант, а непройденный протокол.

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

8. Цена сети, которую забывают посчитать

Восемь заблуждений о распределённых системах и задержка как распределение, а не как одно число.

Ключевая мысль: цена распределения системы

Ника подошла к главному вопросу своей недели — резать ли монолит. Протокол 08 отвечает не «да» и не «нет», а «посчитай сначала»: он проверяет цену распределения системы до того, как локальный вызов станет сетевым.

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

Задержку меряют распределением, а не средним. Возьми среднее время полного цикла и значения 95–99-го процентилей для одного перехода, затем умножь на число последовательных сервисов. Примеры из источника: 10 переходов по 100 мс дают 1000 мс; среднее 60 мс рядом с 95-м процентилем 400 мс показывает, почему чужие числа нельзя брать как норматив — их измеряют в своей среде.

Дальше — три пункта, которые обычно всплывают уже в проде:

  • Неизвестный результат. Запрос мог выполниться, хотя ответ потерялся. Тайм-аут и предохранитель ограничивают последствия, но эту неопределённость не убирают — поведение при неизвестном исходе проектируют отдельно.
  • Политика версий. Область управления, масштаб поддерживаемой части, число одновременно живущих версий и правило устаревания. Нумерация без этих решений политикой не является.
  • Отказ компенсации. Нарисуй основной путь, компенсации уже выполненных шагов и отдельный путь восстановления на случай, когда сама компенсация откажет.

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

9. Где на самом деле проходит граница

Архитектурный квант: область независимой поставки с единым набором свойств.

Ключевая мысль: архитектурный квант

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

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

Проверки границы:

  1. Деловая цель. Граница обслуживает отчётливую цель, а не совпадение с процессом или именем сервиса.
  2. Независимая поставка. Кандидат выпускается без обязательной совместной поставки остальных.
  3. Обязательные ресурсы внутри. Всё, без чего часть не работает, входит в границу. Общая обязательная база объединяет несколько сервисов в одну область свойств — этот пункт и переломил счёт у Ники.
  4. Локальный смысл модели. Если одна сущность означает разное в разных процессах, держи отдельные представления внутри ограниченных контекстов.
  5. Четыре слоя связанности. Семантическая задана самой задачей; реализационная — выбранной формой решения; статическая — общими компонентами и данными; динамическая — вызовами во время работы. Естественную семантическую зависимость техническим приёмом не убрать.
  6. Ожидание во время работы. Обязательный синхронный ответ передаёт соседу и задержку, и отказ.
  7. Платформа внутри границы. Свойства оркестратора и управляемых блоков — часть профиля, а обещание провайдера требует проверки.

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

10. Событие, поручение и три окна потери

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

Ключевая мысль: три окна потери сообщения

Ника решила, что часть работы уедет в асинхронный поток. Дальше два протокола идут парой: 14 отвечает, ЧТО за сообщение, а 15 — как оно доживёт до конца.

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

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

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

  1. между отправкой и устойчивым приёмом — закрывается сохраняемой очередью и ожиданием подтверждения физической записи брокером;
  2. между чтением и завершением обработки — закрывается подтверждением от клиента: элемент остаётся закреплённым, пока потребитель не отчитался;
  3. на записи в базу — закрывается ACID-транзакцией, после чего сообщение удаляется в той же операции, если платформа это поддерживает.

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

11. Правило, которое проверяет себя само

Как превратить архитектурную договорённость в сигнал, порог и реакцию.

Ключевая мысль: исполняемая функция пригодности

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

Порядок сборки:

  1. Назови защищаемую цель — свяжи правило с деловым результатом и архитектурным свойством.
  2. Сформулируй само правило — допустимые источники обращения, цель, запрещённые обходы и обоснование.
  3. Выбери сигнал по риску. Числовому состоянию соответствует метрика, поведению во времени — монитор, изменению — обработчик события, статической структуре — тест, устойчивости к отказу — контролируемый эксперимент.
  4. Откалибруй вычисление и порог. Для графа потока одной функции цикломатическая сложность считается как CC = E - N + 2, а при P компонентах связности — CC = E - N + 2P; для обычного продуктового кода значение меньше 10 считают распространённой верхней границей, стремясь к значению меньше 5. Для структуры пакетов расстояние считается как D = |A + I - 1|, и пример ideal = 0.0, tolerance = 0.5 зависит от проекта и требует калибровки.
  5. Возьми сильнейший подходящий механизм — запрет циклов в графе зависимостей, проверка расстояния пакетов, закреплённое направление слоёв.
  6. Встрой проверку в контур изменения и заранее согласуй реакцию: вернуть реализацию, изменить практику или пересмотреть исходное решение.
  7. Проверяй жизнеспособность самого правила на обзорах: сигнал обязан отличать деградацию системы от устаревшей модели.

Самое честное место протокола. Для субъективного условия оставляют ручную проверку, а не имитируют автоматизацию: одиночный косвенный показатель не доказывает свойство целиком. Ложная автоматизация хуже отсутствующей — она успокаивает.

12. Риск-шторм и честные границы пакета

Как команда оценивает риск числом — и где сам пакет обязан сказать «здесь я молчу».

Ключевая мысль: балл риска: влияние × вероятность

Последнее, что делает Ника перед тем, как объявить решение принятым, — собирает коллег на риск-шторм по протоколу 22. Правило счёта простое: балл риска — это влияние × вероятность, где каждая ось оценивается как 1 (низкая), 2 (средняя) или 3 (высокая).

Как проходит сессия:

  1. Одна предметная область или одно критичное свойство и актуальная схема — не всё сразу.
  2. Пакет с материалами рассылается заранее; на встрече люди уже думают, а не читают.
  3. Каждый участник оценивает независимо: сначала влияние, потом вероятность.
  4. Значения 1–2 — низкий риск, 3–4 — средний, 6–9 — высокий. Неизвестную вероятность временно считают высокой, а незнакомая участнику технология получает 9, пока не появятся данные.
  5. Отметки сводятся на общую схему. Совпадения подтверждают быстро, а расхождения разбирают по влиянию, вероятности и эксплуатационным фактам.
  6. Для каждого существенного риска сравнивают стоимость меры с остаточным баллом; дорогой компромисс выносят к бизнес-стейкхолдерам.

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

А теперь то, о чём Ника прочитала в README, и это оказалось самым полезным абзацем. Пакет честно называет свои границы: он не заменяет книгу-источник, ссылается только на страницы, вычисленные из своих KU, и не додумывает отсутствующее число, формулу или рисунок. Вне его области остаются произвольные диаграммы, контракты REST/OpenAPI/GraphQL/gRPC, ETL, развёртывание, инциденты и командные ритуалы. Инструмент, который знает, где он молчит, безопаснее инструмента, у которого на всё есть ответ.

Частые вопросы

Пакет заменяет книгу-источник?

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

Чем шлюз отличается от навыков architecture-decision-records и c4-architecture?

Шлюз принимает решение, они его оформляют. Записать принятый выбор как ADR — к architecture-decision-records или capture-adr; нарисовать или проверить C4 — к c4-architecture. Шлюз может сформулировать, какое свойство обязан показать артефакт, но не делает его сам.

Что делать, если вопросов честно два — и про границы, и про события?

Начинай с более раннего необратимого решения. Цену распределения (протокол 08) проверяй до гранулярности микросервисов (19); семантику сообщения (14) определяй до механизма доставки (15), но если проблема уже сформулирована как потеря или порядок сообщений — начинай с доставки. Второй маршрут берётся только как явно названный следующий шаг.

Мне нужен глубокий поиск по книге. Как подключить лексический срез?

Командой dz brain add --from-pack @dzhechkov/skills-book-fundamental-software-architecture. Это явный локальный импорт среза на 315 KU: исходный PDF и извлечённый корпус он не копирует.

Почему семейство архитектурной коммуникации не срабатывает само?

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

Агент назвал число, которого в источнике нет. Это нормально?

Нет, это прямое нарушение протокола: пакет обязан не додумывать отсутствующее число, формулу или рисунок, а помечать их как неизвестные и предлагать способ добыть — измерение, инвентаризацию, сессию с участниками или POC. Числа вроде порога цикломатической сложности или tolerance = 0.5 в источнике названы проектно-зависимыми и требуют калибровки, а не переноса как норматива.

Курс учит книге или пакету?

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