Спроектируйте 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 в проде вместо миграций