Уровень зрелости 1: Стартовый
Стартовый уровень Use Case Pattern: UseCase + Handler на одну операцию, одна модель данных, общий маршрут. Подходит для MVP, CRUD-сервисов, внутренних инструментов.
← назад к методологии · уровень 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 + Dispatcher | usecase-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: разделение чтения и записи.
Что почитать рядом
- Use Case Pattern (методология) — все четыре уровня и их место в общей картине.
- Библиотека usecase-pattern — каркас, который вы подключаете на этом уровне.
- Use Case спецификация (Tier A) — как описывать сервис на этом уровне зрелости.
- REST API Style Guide — контракты для внешнего API.