Нужно ли создавать отдельный сервис для создания платежа с проверками и конструированием объекта?
Что проверяют
Понимаете ли вы разницу между отдельным классом сервиса и отдельным микросервисом, и знаете ли, где в приложении на Spring проходят границы слоёв и транзакции. Вопрос почти всегда про слой, а не про инфраструктуру.
Как отвечать
Сначала уточните, о каком сервисе речь, вслух. Если про слой, ответ да: контроллер принимает запрос и проверяет форму данных, сервис держит бизнес-правила и границу транзакции, репозиторий работает с базой. Сборка платёжного объекта, лимиты, выбор валюты и комиссии это бизнес-правила, им не место ни в контроллере, ни в сущности JPA.
Дальше разложите проверки по местам:
- обязательность и формат полей: аннотации на объекте запроса и
@Valid, отказ с кодом 400 без похода в базу; - инварианты домена, например положительная сумма и валюта из справочника: конструктор или фабричный метод доменного объекта, чтобы некорректный платёж нельзя было создать в принципе;
- правила, которым нужны данные из базы, например лимит и статус счёта: сервис, внутри транзакции, вместе с записью результата.
Отдельный микросервис это уже другое решение. Его оправдывают собственный цикл выпуска, отдельный контур безопасности для платёжных данных, своя нагрузка или отдельная команда. Платят за это сетевыми сбоями, согласованностью через события и заметно более дорогим тестированием.
Где спотыкаются
Слышат слово «сервис» и уходят рассказывать про микросервисы, брокер и оркестрацию, хотя в вопросе речь про класс на сто строк. Уточняющий вопрос здесь добавляет баллов, а не отнимает.
Делают слой анемичным: сервис разрастается до тысячи строк, а сущность состоит из геттеров и сеттеров. Часть правил должна жить в самом объекте, тогда недопустимое состояние недостижимо.
Промахиваются с транзакцией. Вызывают метод с аннотацией транзакции изнутри того же класса и удивляются, что прокси не сработал, либо дёргают внешнюю платёжную систему внутри транзакции и держат соединение с базой всё время сетевого вызова.