Уровень зрелости 1: Стартовый

Стартовый уровень Use Case Pattern: UseCase + Handler на одну операцию, одна модель данных, общий маршрут. Подходит для MVP, CRUD-сервисов, внутренних инструментов.

Статья внедрена в скилл AI-агента ucp-pattern-review / ucp-pattern-design Эталонная библиотека к статье usecase-pattern Use Case Pattern уровень 1

← назад к методологии · уровень 1 из 4

Какую проблему решает

Бизнес-логика тонкая, времени мало, нужно собрать рабочий продукт за разумный срок. Полноценный DDD будет избыточен и съест бюджет, а просто «контроллер → сервис → репозиторий» через полгода превращается в спагетти из-за того, что бизнес-операции не разделены явно.

Стартовый уровень даёт ровно одну дисциплину: каждую бизнес-операцию выделить в отдельный UseCase + Handler. Этого достаточно, чтобы не утонуть в сервис-классах с 30 методами.

Когда подходит

  • MVP, прототип, внутренний инструмент.
  • CRUD-сервис: справочник, админка, простая интеграция.
  • Команда из 1–3 разработчиков, домен «понятный за полчаса».
  • Жизненный цикл сервиса — год-два, после чего его либо перепишут, либо он уйдёт.

Что должно быть

Каждая бизнес-операция — отдельный UseCase + Handler. Создание заказа — один UseCase. Получение заказа по id — другой. Не «один OrderService с пятью методами» — пять отдельных пар.

Один общий маршрут на все операции. Контроллер не знает, какой именно обработчик вызовется — отдаёт UseCase в диспетчер, диспетчер находит handler по типу. Диспетчер уже встроен в библиотеку.

Одна модель данных. То, что приходит из API, и то, что лежит в БД, — может быть одной и той же или связано простым маппингом. Никаких отдельных «доменных моделей», «Value Objects» — всё это будет на следующих уровнях, когда понадобится.

Транзакция на уровне Handler. Один @Transactional на handler — всё или ничего. Никаких размазанных транзакций по сервисам.

Метрики на каждый UseCase автоматически. Сколько раз вызывалась операция, сколько падала, как долго работала. Этим занимается библиотека.

Как это должно выглядеть

  • Каждая операция — два класса: <Operation>UseCase (record с входными полями) и <Operation>UseCaseHandler (с методом handle и аннотацией Spring-компонента).
  • Контроллер делает три вещи: распарсил запрос → передал в диспетчер → завернул ответ.
  • Бизнес-проверки и обращения к БД — внутри handler, нигде больше.
  • Тесты — на handler, без mock-инфраструктуры контроллера и репозитория сразу.

Что НЕ нужно делать на этом уровне

  • Разделять команды и запросы (UseCaseCommand / UseCaseQuery) — это уровень 2.
  • Заводить отдельные доменные классы (Aggregate, Value Object) — это уровень 3.
  • Строить порты и адаптеры (core / adapter) — это уровень 4.
  • Пускать события через outbox — обычно не нужно.

Каждое из этих усложнений стоит времени, и без боли, которую они решают, оно не окупается.

Библиотеки и инструменты

ЧтоЧем
Каркас UseCase + Handler + Dispatcherusecase-pattern-starter
Web-слойSpring Boot, OpenAPI Codegen
АвторизацияSpring Security + OAuth2 (для внешних сервисов)
ХранилищеjOOQ или JPA — что команде ближе
МетрикиMicrometer (идёт со starter-ом)
ТестыJUnit 5 + Spring Boot Test

Никаких MapStruct, ddd-building-blocks, Outbox — пока. Они нужны на следующих уровнях.

Признаки, что пора уходить на уровень 2

  • Чтения и записи мешают друг другу — длинные SELECT блокируют, или записям нужна агрессивная изоляция, которую запросы не выдержат.
  • Появились запросы с тяжёлой агрегацией и нагрузкой на единицу времени, которые не стыкуются с обычным CRUD.
  • Хочется отдельных политик кэширования или транзакций для чтений.

Тогда — Уровень 2: разделение чтения и записи.

Что почитать рядом