У меня очень простой экспресс-сервер JS, который принимает запрос от клиента, выполняет некоторую бизнес-логику и отвечает клиенту. Конвейер запроса-ответа обрабатывается контроллером, а бизнес-логика выполняется на уровне сервиса. Код функционален, но я не уверен, что способ, которым я возвращаю ошибки в контроллер из уровня обслуживания, является правильным.
Контроллер выглядит примерно так:
async createAnOrder(req, res, next) {
try {
// Input validations
if (!req.body.name){
throw new ClientFacingError(ERROR_CODES.BAD_REQUEST, "Name is missing")
}
let newOrder = new Order();
let validationDictionary = new ValidationDictionary();
if (!await orderService.createOrder(newOrder, validationDictionary)){
return next(new ClientFacingError(ERROR_CODES.BAD_REQUEST, validationDictionary.getErrorMessage()));
}
res.json({
orderId: newOrder.id
})
} catch (err) {
if (err instanceof ClientFacingError) {
res.status(err.code).json({ message: err.message })
} else {
res.status(500).json({ message: "Internal Error" })
}
}
}
OrderService выглядит примерно таквот так:
async createOrder(newOrder, validationDictionary) {
// Business logic validation
if (await orderDb.hasOrder(newOrder)) {
validationDictionary.addError("Invalid Order", "Order already exists");
return false;
}
await orderDb.createOrder(newOrder);
return true;
}
Я пытаюсь разделить заботу между бизнес-уровнем и всем остальным. Мне также нужен умный контракт между методами уровня сервиса и контроллерами.
Я думаю, что я пытался сделать следующее:
- Проверка входных данных происходит на уровне контроллера (инфраструктуры)проверки, связанные с бизнесом, происходят только на уровне обслуживания
- Методы уровня обслуживания возвращают значение true, если операция прошла успешно, и false, если имеются ошибки проверки бизнеса.
- Любые ошибки, возникающие с помощью методов уровня обслуживания, относятся к среде выполнения. ошибки, которые обнаруживаются контроллерами и возвращаются клиенту как внутренняя ошибка.
Другой способ - придерживаться принципа CQS. Метод сервисного уровня не должен возвращать значение, а вместо этого выдает исключение, указывающее на ошибку. Проблема с этим подходом состоит в том, что у контроллеров нет контекста того, может ли сообщение об ошибке быть возвращено клиенту. Возможно, я смогу выбросить исключение ClientFacingError из сервисного уровня, который может использоваться контроллером, чтобы решить, можно ли вернуть сообщение об ошибке клиенту, но мне кажется, что я связываю сервисный уровень с уровнем инфраструктуры.