Общая проблема
При написании метода обслуживания есть свои преимущества и недостатки, возникающие при создании многих исключений по сравнению с абстрагированием их в общий ServiceException
. Если вы выбрасываете много исключений, вы сообщаете клиенту, что именно пошло не так, чтобы клиент мог более разумно справиться с ошибкой. Если вы абстрагируете их в один ServiceException
(например, через обтекание исключений ), то вы скрываете детали того, что пошло не так, что может быть полезно в некоторых сценариях, но вредно в других.
Например, может быть полезно скрыть детали ошибок в классе DAO, выдав универсальный DaoException
. Таким образом, клиенты не должны знать, читаете ли вы из файла, веб-службы или реляционной базы данных. Но допустим, что вы проверяете пользовательский ввод, и есть по крайней мере четыре вещи, которые могут пойти не так с пользовательским вводом. Разве не разумнее в последнем случае выбросить четыре разных исключения, по одному для каждой вещи, которая пошла не так с проверкой?
Моя конкретная проблема
В моем текущем проекте я работаю над сервисным методом, который сохраняет древовидную структуру в реляционной базе данных. Оно должно проверять дерево, и есть как минимум четыре вещи, которые могут быть неверны с деревом. Может быть дублированный узел или узел может не иметь своих обязательных полей X, Y, Z. Таким образом, для сервисного метода имеет смысл выдать четыре разных исключения: DuplicateNodeException
, MissingXException
, MissingYException
, MissingZException
.
Но метод обслуживания также использует класс DAO, который выбрасывает DataAccessException
через JdbcTemplate. Я хотел бы знать, как справиться с этим DataAccessException
. Имеет ли смысл обернуть его как ManagerException
, а затем снова как ServiceException
и обработать его как ServiceException
? Тогда я бы смешал оба подхода: (а) выбрасывать особые описательные исключения и (б) генерировать исключения исключительной оболочки. Это хорошая идея, чтобы смешать эти подходы здесь?
Причина, по которой я спрашиваю, состоит в том, что мне немного странно отлавливать эти четыре исключения, связанные с валидацией, а затем, кроме того, отлавливать общий неописуемый ServiceException
. Это кажется странным, потому что ServiceException
настолько абстрагирован, что на первый взгляд невозможно сказать, что пошло не так, вам придется проверить журнал и прочитать сообщение об исключении или перейти по иерархии вызовов в коде. Поэтому я прошу проверить, действительно ли это хорошая практика, или обычная, или разумная, - смешивать эти два подхода, потому что интуитивно это кажется мне странным. Есть ли параллели в ядре Java, где оба подхода к обработке исключений используются в одном и том же методе?
Возможное решение (согласно ответу Андреаса)
Имеет ли смысл обрабатывать подобные исключения в моем классе обслуживания? Ниже приведен псевдокод, представляющий возможное решение. Таким образом, я не создаю бесполезную, проверенную, неописуемую исключительную ситуацию ServiceException, но у меня есть универсальное средство для непроверенных исключений (перехватывая исключение в конце). Что вы думаете об этом решении?
class HttpService {
private Service service;
// ...
public HttpServiceResponse saveTree(Node root) {
try {
service.saveTree(root);
} catch (DuplicateNodeException e) {
return HttpServiceResponse.failure(DUPLICATE_NODE_EXCEPTION);
} catch (MissingXException e) {
return HttpServiceResponse.failure(MISSING_X_EXCEPTION);
} catch (MissingYException e) {
return HttpServiceResponse.failure(MISSING_Y_EXCEPTION);
} catch (MissingZException e) {
return HttpServiceResponse.failure(MISSING_Z_EXCEPTION);
} catch (Exception e) {
return HttpServiceResponse.failure(INTERNAL_SERVER_ERROR);
}
}
}