В Use Case Pattern есть два понятия, которые часто путают, потому что у обоих по четыре значения:
- Уровень зрелости (1, 2, 3, 4) — характеристика кода сервиса: какие архитектурные приёмы применены. Это про что лежит в репозитории.
- Tier (0, A, B, C) — характеристика спецификации сервиса: насколько подробна спека и откуда она получена. Это про что лежит в
docs/spec/.
Понятия связаны, но связь не один-к-одному: один Tier может покрывать несколько уровней зрелости.
Уровень зрелости — про целевую архитектуру
Описывает, какой код мы пишем. Команда повышает уровень по мере роста сложности сервиса.
| Уровень | Что добавляется | Подходит для |
|---|---|---|
| Уровень 1: Стартовый | UseCase + UseCaseHandler на каждую операцию, одна модель данных | MVP, CRUD-сервисы, внутренние инструменты |
| Уровень 2: CQRS | UseCaseCommand / 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-сервис ± CQRS | Tier 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, всё симметрично». Не работает по двум причинам:
- Команды живут на DDD без Hexagonal. Доменный слой с агрегатами и событиями окупается уже на сервисах с инвариантами. Изоляция через порты, Gradle-модули и ArchUnit — отдельный шаг с собственной стоимостью. Объединение этих уровней заставило бы команды платить за hexagonal-разметку даже там, где хватит DDD.
- Tier 0 не вписывается в шкалу 1–4. Это «откуда взяли спеку», а не «куда движемся». Сервис, восстановленный в Tier 0, может быть на любом уровне — от тривиального CRUD до полноценного DDD. Притянуть Tier 0 в шкалу зрелости не получится.
Как выбрать на практике
Алгоритм короткий:
- Спека уже есть и сервис уже в проде? → Tier 0 для онбординга, потом миграция через
ucp-spec-designв нужный Tier A/B/C. - Сервис новый, бизнес-бриф есть? → выбираем Tier по архитектурному плану:
- Справочник, админка, CRUD → Tier A (или B, если хочется UCP-слоистости).
- Сервис с операциями, без инвариантов в домене → Tier B.
- Order / Payment / Reservation, есть инварианты → Tier C.
- 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, уровень зрелости, скилл и библиотека связаны между собой.
- Как применять — пошаговый сценарий: от бизнес-брифа до прода.