← Назад к списку
Системный дизайнJava и KotlinSenior

Спроектируйте REST-сервис заказов на Spring Boot: слои, обработка ошибок, идемпотентность, миграции и наблюдаемость.

Короткий ответ

  • Слои: controller → service → repository, DTO отдельно от сущностей
  • Валидация на входе (Bean Validation), глобальный @ControllerAdvice с ProblemDetail
  • Идемпотентность POST через Idempotency-Key и уникальный индекс
  • Транзакции на сервисном слое, короткие; версии API через префикс /v1
  • Миграции схемы — Flyway/Liquibase, не ddl-auto
  • Наблюдаемость: Actuator, Micrometer, трассировка, структурные логи с correlation id
  • Пагинация, сортировка и фильтры на списковых эндпоинтах

Хороший ответ — слоистый сервис с DTO, централизованной обработкой ошибок, идемпотентной записью, миграциями и метриками из коробки.

Как сказать вслух

пример ответа

Я разделю сервис на три слоя: контроллеры принимают и валидируют DTO, сервисный слой держит бизнес-логику и транзакции, репозитории работают с базой. Наружу никогда не отдаю JPA-сущности — только DTO. Ошибки обрабатываю централизованно через ControllerAdvice в формате problem detail. Создание заказа делаю идемпотентным: клиент шлёт ключ идемпотентности, а уникальный индекс в базе защищает от дублей при ретраях. Схему веду миграциями Flyway, а мониторинг — метрики и трейсинг через Actuator и Micrometer.

Подробный ответ

Основной ответ

Архитектура: REST-контроллеры (ресурсные URL, правильные коды: 201 с Location, 400/404/409, 422), DTO + MapStruct, сервисный слой с @Transactional (короткие транзакции, без внешних HTTP-вызовов внутри), Spring Data JPA с явными стратегиями выборки против N+1. Ошибки — @RestControllerAdvice, RFC 7807 ProblemDetail, без утечки стектрейсов. Идемпотентность: PUT идемпотентен по природе; для POST — заголовок Idempotency-Key, таблица обработанных ключей с уникальным индексом, при повторе возвращаем сохранённый результат; оптимистическая блокировка @Version против конкурентных обновлений. Схема БД — Flyway-миграции в CI, ddl-auto=validate. Наблюдаемость: Actuator health/readiness для k8s, метрики Micrometer (RPS, латентность, ошибки), OpenTelemetry-трассировка, correlation id в логах. Безопасность: Spring Security, JWT/OAuth2 resource server. Конфигурация по профилям, секреты вне кода. Тесты: слайсы (@WebMvcTest, @DataJpaTest) + Testcontainers для интеграционных.

Ключевые моменты

  • Границы слоёв. Сущности не покидают сервисный слой; DTO и мапперы изолируют API-контракт от схемы БД.
  • Идемпотентность записи. Idempotency-Key + уникальный индекс в БД — ретраи клиента и сети не создают дублей.
  • Контракт ошибок. Единый формат ProblemDetail, предсказуемые коды; валидация через Bean Validation на DTO.
  • Эксплуатация. Flyway, Actuator-пробы, метрики и трейсинг — часть дизайна, а не доработка потом.

Практический контекст

Такой вопрос проверяет способность собрать production-ready сервис, а не CRUD из туториала. Интервьюер слушает, что кандидат сам поднимет темы идемпотентности, миграций и наблюдаемости до наводящих вопросов. Частые уточнения: как не словить дубль заказа при таймауте и ретрае, где проходит граница транзакции, почему нельзя звать внешний API внутри неё, как версионировать контракт без слома клиентов.

Частые ошибки

  • Отдают JPA-сущности прямо из контроллера, связывая API со схемой БД
  • Забывают про идемпотентность POST — ретраи клиентов создают дубли заказов
  • Ведут схему через hibernate ddl-auto=update в проде вместо миграций

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru