← назад к методологии

В Use Case Pattern есть два понятия, которые часто путают, потому что у обоих по четыре значения:

  • Уровень зрелости (1, 2, 3, 4) — характеристика кода сервиса: какие архитектурные приёмы применены. Это про что лежит в репозитории.
  • Tier (0, A, B, C) — характеристика спецификации сервиса: насколько подробна спека и откуда она получена. Это про что лежит в docs/spec/.

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

Уровень зрелости — про целевую архитектуру

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

УровеньЧто добавляетсяПодходит для
Уровень 1: СтартовыйUseCase + UseCaseHandler на каждую операцию, одна модель данныхMVP, CRUD-сервисы, внутренние инструменты
Уровень 2: CQRSUseCaseCommand / UseCaseQuery, отдельная Read ModelСервисы, где чтение и запись разные по нагрузке и форме данных
Уровень 3: DDDАгрегаты, value objects, доменные события, Handler — оркестраторСервисы с инвариантами в домене (Order, Payment, Reservation)
Уровень 4: HexagonalПорты и адаптеры, изоляция домена от инфраструктуры, ArchUnit-правилаКогда планируется замена инфраструктуры без переписывания домена

Повышается легко, понижается тяжело. Не строить уровень 4 там, где хватит уровня 1.

Tier — про форму спеки и источник входа

Описывает, какой текст лежит в docs/spec/<service>.md. Tier выбирается в момент написания спеки и определяется тем, что есть на входе у автора и какой архитектурный уровень планируется.

TierИсточник входаЧто в спеке
Tier 0Существующий код (brownfield, без бизнес-брифа)16 разделов as-is, отсутствующие данные помечены литералом not-declared. Реверс-инжиниринг через ucp-spec-tier-0
Tier AБизнес-бриф, классическая слоёная архитектураМинимум: глоссарий, ER-схема, операции, правила, ошибки. Без UseCase, без агрегатов
Tier BБизнес-бриф, UCP-сервис ± CQRSTier A + UseCase-ы, опционально Read Model. Без агрегатов и доменных событий
Tier CБизнес-бриф, DDD или HexagonalПолные 16 разделов: агрегаты, value objects, доменные события, саги

Tier 0 — отдельная история: это не уровень зрелости и не цель, а способ восстановить спеку из кода. Из Tier 0 потом переходят в A/B/C через тот же ucp-spec-design, уже с бизнес-вводом.

Матрица соответствия

Уровень 1Уровень 2Уровень 3Уровень 4
Tier A— (до UCP)
Tier B
Tier C

Главное наблюдение: Tier C покрывает и уровень 3 (DDD), и уровень 4 (Hexagonal). Форма спеки у них идентична — те же 16 разделов с агрегатами, событиями и сагами. Отличие в коде, не в спеке: на уровне 4 добавляется разметка пакетов через @Port / @Adapter и проверка границ через hexagonal-architecture-archunit. Спеке про это знать не нужно.

Аналогично Tier B покрывает зрелость 1 и 2 — Read Model добавляется в коде, не в шаблоне спеки.

Tier 0 в матрицу не входит: он описывает существующий код «как есть» и применим к сервису любого уровня зрелости. Это не цель, а способ восстановить спеку с нуля. После Tier 0 сервис мигрирует в полноценный Tier A/B/C через ucp-spec-design уже с бизнес-вводом — там и проявляется уровень зрелости.

Почему DDD и Hexagonal — это два уровня, а не один

Часто звучит вопрос «давайте объединим DDD и Hexagonal в один уровень — будет три уровня, три Tier, всё симметрично». Не работает по двум причинам:

  1. Команды живут на DDD без Hexagonal. Доменный слой с агрегатами и событиями окупается уже на сервисах с инвариантами. Изоляция через порты, Gradle-модули и ArchUnit — отдельный шаг с собственной стоимостью. Объединение этих уровней заставило бы команды платить за hexagonal-разметку даже там, где хватит DDD.
  2. Tier 0 не вписывается в шкалу 1–4. Это «откуда взяли спеку», а не «куда движемся». Сервис, восстановленный в Tier 0, может быть на любом уровне — от тривиального CRUD до полноценного DDD. Притянуть Tier 0 в шкалу зрелости не получится.

Как выбрать на практике

Алгоритм короткий:

  1. Спека уже есть и сервис уже в проде? → Tier 0 для онбординга, потом миграция через ucp-spec-design в нужный Tier A/B/C.
  2. Сервис новый, бизнес-бриф есть? → выбираем Tier по архитектурному плану:
    • Справочник, админка, CRUD → Tier A (или B, если хочется UCP-слоистости).
    • Сервис с операциями, без инвариантов в домене → Tier B.
    • Order / Payment / Reservation, есть инварианты → Tier C.
  3. Tier выбран — определяем уровень зрелости кода:
    • Tier A → классическая слоёная (до UCP), уровень не назначается.
    • Tier B → уровень 1 или 2 (CQRS добавляется по нагрузке).
    • Tier C → уровень 3 (DDD), повышаем до 4 (Hexagonal), когда домен достаточно дорог и инфраструктура достаточно изменчива.

Правило стартового решения: берите на Tier ниже, чем кажется нужным. Tier повышается легче, чем понижается.

FAQ

У меня сервис на уровне 2 (CQRS). Какой Tier у спеки? Tier B. Read Model описывается отдельным запросом в §3 операций, отдельной таблицы в спеке для неё не нужно.

Можно ли быть на уровне 4 (Hexagonal), но без DDD? Технически да — порты и адаптеры применимы и к анемичной модели. На практике редко: если бизнес-логика тонкая, hexagonal-разметка не окупается, и команда обычно остаётся на уровне 1–2. Tier у такого сервиса будет B, не C.

Tier 0 — это «плохая» спека? Нет. Это честная спека существующего кода. Отсутствующие данные помечены not-declared — видно, где знание потеряно. Tier 0 нужен для онбординга, разбора legacy и подготовки к рефакторингу. Из Tier 0 переходят в полноценный Tier A/B/C, когда появляется бизнес-вход.

Tier C для CRUD-справочника — это перебор? Да. Если в домене нет инвариантов и агрегатов — Tier C даст пустые §8 events и §12 sagas, прочитать спеку станет тяжелее. Tier A или B — нормальный выбор для справочников.

Куда дальше

  • Уровни зрелости 1–4 — детально по каждому уровню кода.
  • Use Case спецификация: универсальный шаблон — 16 разделов спеки, Tier A/B/C/0.
  • Онтология UCP — как Tier, уровень зрелости, скилл и библиотека связаны между собой.
  • Как применять — пошаговый сценарий: от бизнес-брифа до прода.