dmitriylanets
@dmitriylanets
веб-разработчик

Правильно ли выбрасывать исключения в бизнес логике?

В последнее время встречаю много критики по поводу данного подхода, но все же насколько правильно заложить исключительные ситуации для метода сервиса бизнес логики через вариации Exceptions
try{
   $order = $orderService->createOrderAndNotify($orderRequest);
   return $this->view("success",[
      "orderId" => $order->getId()
   ]);
}
catch(OrderValidationException $ex){
   $logger->warning("error valid order", $ex->getErrors());
   return $this->view("warning",[
       "errors" => $ex->getErrors()
   ]);
}
catch(OrderException $ex){
   $logger->error($ex->getMessage());
   return $this->view("error");
}


иерархия исключений Order\Exceptions
OrderException extends RuntimeException
OrderValidationException extends OrderException
OrderNotFound extends OrderException


вижу приемущества:
1. конкретный ответ метода, а не какой то специализированный DTO отдающий все на свете
2. обработка исключений в зависимости от ситуации и логики приложения
3. тестируемость и документированность (phpunit,docblock)
4. передача доп. данных в исключениях
  • Вопрос задан
  • 1262 просмотра
Решения вопроса 1
Я считаю это хорошей практикой. Исключительная ситуация - это та, при которой программа выполняется не так, как ожидалось. Но, позвольте, я ожидаю, что заказ пройдет валидацию. Я ожидаю, что заказ завершится успехом. Поэтому OrderValidationException, OrderException - исключительные ситуации. Исключительной ситуацией не является, например, отмена пользователем заказа - глупо выбрасывать исключение по клику на Cancel.

Исключения гораздо глубже, чем просто "исключительная ситуация". Они помогают развести обработку ошибок по разным уровням абстракции, а использование разных типов исключений позволяет обрабатывать конкретные ошибки там, где их нужно обработать (на нужном слое). Исключения очень помогают в локализации ошибки в дальнейшем, они позволяют избавиться от простыни If .. else, проверок на null, false и прочей ереси. Они, чаще всего, делают код чище.

Но пользоваться ими стоит аккуратно, все-таки стоит разделять исключительную ситуацию и вполне нормальную, штатную ветку исполнения. Так, если заказов нет - это НЕ исключение, тут можно вернуть null - допустимо (хотя некоторые и тут выбрасывают исключение, потому что очень соблазнительно привязать код исключения к HTTP кодам). А если у вас аплоад документов, и юзер пытается загрузить файл слишком большой, то это уже исключение.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
FanatPHP
@FanatPHP
Чебуратор тега РНР
Ответ на вопрос из заголовка простой: исключение выбрасывается тогда, когда код не в состоянии выполнить работу, для которой он предназначен. Это простое правило, общее для программирования в целом, и безнес логика в этом смысле ничем не отличается от любого другого кода.

Я бы разделил валидацию и создание заказа.
Для валидатора ошибки введенных данных - это не исключителная ситуация, а соверешнно штатная.
То есть можно проверить результат валидации простым условием, без всяких исключений.


По зрелом размышлении я всё-таки сглашусь, что подход с выбросом исключения при валидации вполне может применяться.

Но вот код, который лежит внутри catch(OrderException $ex){ является избыточным. Логирование ошибки и вывод стандартного сообщения клиенту - это то, что должен делать централизованный обработчик ошибок, который в любом случае должен присутствовать в приложении. То есть здесь этот код явно лишний.
Ответ написан
php666
@php666
PHP-макака
Нет, это плохая практика.

Исключительная ситуация на то и исключительная. Это ошибка запроса, нет коннекта к БД или отсутствие записи, которая, как мы уверены, должна существовать и тд. Это событие, после которого работа кода НЕВОЗМОЖНА.

Оборачивая в исключения бизнес-логику ты расписываешься в кривой архитектуре. Валидация - это отдельный слой, который не должен давать никаких исключений, это штатный механизм системы, который должен отдать корректный ответ клиентскому коду, который его использует.
Ответ написан
@Arik
может интересно будет
https://github.com/adelf/acwa_book_ru/blob/master/...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы