Как обрабатывать исключения в многослойном проекте и где лучше пробрасывать ошибки?
Что проверяют
Знаете ли вы, где исключение ловить, а где отпускать, и не превращаете ли каждый слой в try/catch с логом. Следом обычно спрашивают про глобальный обработчик в ASP.NET Core и про разницу между throw; и throw ex;.
Как отвечать
Главное правило: ловите исключение там, где можете с ним что-то сделать. Во всех остальных местах пусть летит вверх.
- доступ к данным: оборачивайте низкоуровневые ошибки, только если меняете их смысл. Например,
DbUpdateExceptionс нарушением уникальности превращается вDuplicateEmailException, а исходное исключение уходит вinnerException, иначе теряется причина. Для точечного перехвата удобны фильтры:catch (SqlException ex) when (ex.Number == 2627); - бизнес-логика: собственные исключения для нарушенных правил (
NotFoundException,ForbiddenOperationException). Ожидаемые исходы вроде ошибок валидации многие команды возвращают черезResult<T>, чтобы не строить поток управления на исключениях; - граница приложения: один глобальный обработчик. В ASP.NET Core это
UseExceptionHandlerвместе сAddProblemDetails(), а с .NET 8 интерфейсIExceptionHandler. Он логирует ошибку один раз, сопоставляет тип с HTTP-кодом (404, 409, 422, 500) и отдаётProblemDetailsбез стека и текста SQL; - повторный выброс:
throw;сохраняет стек,throw ex;его обнуляет. Для обёртки:throw new DomainException(message, ex); - отмена:
OperationCanceledExceptionпри оборванном запросе не ошибка, логировать её какErrorне нужно.
Тестируйте именно маппинг: сервис бросает NotFoundException, эндпоинт отдаёт 404 с нужным телом.
Где спотыкаются
Ловят, логируют и пробрасывают на каждом уровне. Одна ошибка оказывается в логах трижды, а разбираться всё равно приходится с самым нижним исключением.
Бросают голый Exception с текстом «не удалось получить пользователя». Его нельзя поймать избирательно, и обработчик на границе не поймёт, что возвращать клиенту.
Глотают исключения: catch { return null; }. Сбой базы превращается в «пользователь не найден», и найти настоящую причину в проде становится почти невозможно.