Перейти к содержанию

D-05 · Границы на старте#

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

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


1. Что выяснить#

Пять вопросов вместо семи: на гринфилде меньше источников. Все отвечаются до написания первой строки кода.

Вопрос Где искать ответ Заполняет ось
Где одно и то же слово означает разное? Требования, разговоры с заказчиком, спор о терминах на встрече Языковая граница
Что обязано меняться атомарно и какие инварианты нельзя нарушать? Требования из W0 Транзакционная граница
Сколько команд будет и когда появится вторая? План найма, а не текущий состав Организационное соответствие
Что по плану будет переписываться в первый год? Роадмап продукта Ожидаемая скорость изменений
У каких частей профиль нагрузки или требования к доступности различаются на порядок? Оценки W1 Технические причины разделения

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

Вопросы, порождающие кандидатов#

  • Если резать по языку — сколько получится частей и какие?
  • Если по транзакционным границам — какие?
  • Что останется, если не резать вовсе?

Третий вопрос обязателен: он и даёт нулевой вариант.

2. Оси и дисквалификаторы#

Оси сравнения. Языковая чистота · транзакционная целостность · организационное соответствие · стоимость ошибки · скорость первого запуска.

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

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

  • Нет наблюдаемости, трассировки и автоматического выката. Для микросервисов это входное требование, а не следствие (OPS-07); у системы, которой ещё нет, его нет по определению. Отвергается разрез целиком — и это единственный из семи, который можно не отвергнуть, а купить: построить входное требование до запуска. Цена покупки называется в ADR, иначе отвержение считается состоявшимся.
  • Сервисов получается больше, чем команд. Одна команда на два сервиса — это не два владельца, а один владелец с двойной эксплуатацией. Отвергается число частей, а не разрез: частей не больше, чем владельцев, и линия перепроводится так, чтобы это выполнялось.
  • У части нет владельца — некому дежурить и отвечать за контракт. Отвергается эта часть, а не разрез: она присоединяется к соседней, у которой владелец есть.
  • Разрез разрывает операцию, обязанную быть атомарной в основном сценарии (DIST-08). Отвергается линия, а не требование атомарности — как и в D-02, D-07: инвариант не обсуждается, обсуждается место разреза.
  • Разрез идёт по техническим слоям — даёт связность на каждое изменение. Отвергается основание линии, а не сама идея резать: линия перепроводится по предмету, а не по слою. Это единственный дисквалификатор, у которого нет законного исхода «оставить как есть»: слой границей не бывает никогда.
  • Планируемый разрез рассекает класс защищаемых данных. На старте это дешевле всего исправить и легче всего проглядеть: классов ещё нет в схеме, они есть только в требованиях. Отвергается положение линии: её двигают, а не оплачивают. Персональные, платёжные и подобные данные стягиваются в одну границу до первой строки кода — потом это миграция (D-07).
  • Части с разными целями по доступности остаются в одном архитектурном кванте — общая база, общий выкат, синхронная связь на каждой операции. На старте это встречается чаще, чем кажется: границы нарисованы, а база одна на всех.

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

  • разрез возможен (дисквалификаторы 1–3 не сработали или куплены) → разрезается квант: части с разными целями получают свои базу и выкат;
  • разрез невозможен → отзывается различие: у частей одна цель по доступности, и та, что слабее, живёт по цели той, что строже.

Отзыв различия — решение, а не умолчание: он записывается в ADR строкой «у части N нет собственной цели по доступности, она живёт по цели M», и с этого момента обещать разные цифры нельзя ни в требованиях, ни в D-10. Молчаливый отзыв — это те самые «разные цифры в требованиях, недостижимые с первого дня».

Силы интеграции: на старте их измеримо две из четырёх#

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

Сила На старте Что делать
Транзакции Измерима: инварианты известны из W0 Работает дисквалификатором, как и в D-02
Рабочий процесс Измерима прогнозом: основные сценарии описаны, частоты оценены на W1 Пометка [прогноз]; пересечение линии на каждой операции основного сценария — довод против линии
Общий код Неизмерима: кода ещё нет Не заполнять и не выдумывать. Проверить при первом же пересмотре границ — к тому времени он появится и уже будет общим
Отношения в данных Неизмерима как факт, но является нашим решением: схему проектируем мы Не «какие связи есть», а «какие связи мы собираемся провести поперёк линии» — и если собираемся, линия под вопросом

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

3. Матрица оценки#

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

  • Словарь пометок: [требования] — из инвариантов и формулировок W0 · [орг] — из состава команд и принятой терминологии · [прогноз] — предсказание с указанием, чем оно подтвердится после запуска · [нет данных].

Пример условный. Форма настоящая, содержание — иллюстрация.

Ось Что записывать в ячейку Модульный монолит Разрез по языку
Языковая чистота Сколько терминов остаётся с двойным значением внутри границы 3 — границы внутри процесса не мешают им пересекаться [орг] 0 — разрез строился по языку [орг]
Транзакционная целостность Какие атомарные операции пересекают границу Ни одной — один процесс Одна: подтверждение резерва билетом [требования]
Организационное соответствие Сколько команд на сколько частей, и когда появится вторая Одна команда, одна кодовая база Одна команда на три сервиса [орг]
Стоимость ошибки Что придётся сделать, если граница окажется ложной Перенести модуль — дни Перенести между сервисами — недели плюс миграция данных
Скорость первого запуска Что нужно построить до первой выкатки Ничего сверх приложения Наблюдаемость, трассировка, автовыкат — до запуска
  • Матрица чаще всего не понадобится: дисквалификаторы отсекут разрезы раньше. Тогда она не заполняется, а вместо неё пишется строка «дисквалификаторы сделали всю работу» с перечнем сработавших (мастер-шаблон).

4. Типовые формы разреза — и какие из них применимы без истории#

Те же формы, что в D-02, раздел 4, но половина из них требует данных, которых на старте нет.

Форма Применима на старте Почему
По поддомену и ограниченному контексту Да Язык существует до кода: он в требованиях и в головах заказчика
По транзакционной границе Да Инварианты формулируются в W0, до первой строки
По бизнес-способности Да, с оговоркой Способности стабильнее команд, но на старте их легко перечислить неверно
По владению данными Частично Модель данных ещё меняется; граница закрепит незрелое решение
По скорости изменений Нет Требует истории. Роадмап — не история, а намерение
По команде Нет Команда одна; план найма меняется чаще, чем архитектура
По профилю нагрузки Нет Оценки W1 — расчёт, а не замер. Кроме того, у выделяемой части должны быть свои данные, иначе это кэш
По техническим слоям Никогда Анти-форма

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

5. Эвристики#

Умолчание — модульный монолит с явными границами модулей. Не из консерватизма: из пяти осей две заполняются фактами, три — прогнозами, а прогнозы на старте ошибаются. Модульный монолит сохраняет право на ошибку (ARCH-01), не отказываясь от дисциплины: модули с явными интерфейсами, запрет на чужие таблицы, проверка зависимостей на сборке.

Границы из языка переживут переход. Единственный источник фактов, доступный до запуска, — то, как заказчик называет вещи. Найденная по языку граница останется верной и после того, как появятся измерения; найденная по прогнозу нагрузки — нет.

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

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

Записать, чем решение станет проверяемым. Через полгода появится история изменений — и вопрос перейдёт в D-02. Здесь надо записать порог: какую долю изменений внутри одного модуля мы считаем приемлемой.

6. Запись в ADR#

Поле ADR Чем заполняется отсюда
Контекст Ответы на пять вопросов, с пометками [требования] / [орг] / [прогноз]
Дисквалификаторы Что отсекло разрезы; обычно это входные требования микросервисов
Рассмотренные варианты Кандидаты и принцип каждого; матрица — если заполнялась
Решение Перечень модулей с владением данными: кто чем владеет и к чему не имеет права обращаться
Обоснование Какие оси заполнены фактами, какие прогнозами, и почему прогнозы не перевесили
Самая дорогая будущая граница По какой линии разрез обойдётся дороже всего — обычно по ней идёт транзакция основного сценария
Последствия Что придётся построить в первый месяц; что станет дороже при росте
Условия пересмотра Раздел 7
Метод D-05 v<версия> · шаблон ADR v<версия> — рыночного снимка нет

7. Условия пересмотра#

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

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

История версий#

Версия Дата Изменение
4.0 2026-09-22 MAJOR, по итогам прогона U-02, развилка Р2. Все семь дисквалификаторов переписаны так, что каждый называет отвергаемое — разрез, число частей, часть, линию, основание линии или требование. У седьмого, о разных целях по доступности в одном кванте, выходов оказалось два и противоположных; правило выбора записано явно, а отзыв различия объявлен решением, а не умолчанием, и обязан попасть в ADR строкой. У первого названа цена покупки: он единственный, который можно не отвергнуть, а оплатить. Старым ADR: он один — ADR-0004 прогона U-02; седьмой дисквалификатор там сработал, выход выбран верно (разрез был невозможен, отозвано различие) и записан строкой, как теперь и требуется. Перепроверять нечего
3.0 2026-09-17 MAJOR. Добавлен дисквалификатор о классе защищаемых данных, рассекаемом планируемым разрезом. На гринфилде он особенно дёшев: классы существуют пока только в требованиях, и стянуть их в одну границу ничего не стоит — в отличие от той же операции после запуска. Старым ADR: перепроверять нечего — ни одного ADR по этому документу не существует (проверено по полю «Метод» всех пятнадцати ADR набора 2026-09-21). Указание «проверить, где по плану окажутся защищаемые данные» адресовано первому применению, а не прошлому
2.0 2026-09-17 MAJOR, по итогам прогона E-02 и разбора глав 6–7 Форда и Ричардса. Добавлен дисквалификатор об архитектурном кванте: разные цели по доступности внутри одного кванта недостижимы с первого дня. Добавлены силы интеграции в объёме, измеримом без истории: транзакции (дисквалификатор), рабочий процесс (по прогнозу), общий код (неизмерим — не заполнять), отношения в данных (не факт, а наше решение). Старым ADR: перепроверять нечего — ADR по этому документу не существует. Указание «проверить, не нарисованы ли границы поверх одной базы при разных целях по доступности» адресовано первому применению
1.0 2026-09-16 Первая версия. Выделена из D-02 v2.1 по итогам прогона E-01: на системе без истории изменений раздел 1 D-02 неприменим, и вопрос там другой — не «где резать», а «какие границы заложить». Пять вопросов, пять осей вместо восьми (три неизмеримы без истории), пометка [прогноз], таблица применимости форм разреза