Задать вопрос

Как лучше реализовать последовательную обработку ошибок?

У меня тут возник вопрос общего характера..
Есть класс, реализующий какие-либо операции низкого уровня (например, PDO). При возникновении ошибки он кидает какой-либо свой exception.
Есть класс более высокого уровня (например, User), который использует внутри себя выше описанный класс. У этого класса тоже есть свои exceptions.
Вопрос: есть ли смысл перехватывать эксепшены низкоуровневого класса (PDOException) и кидать наружу уже экспешены более высокого уровня (UserException)?

Все это может выглядеть например так:
<?php
class User
{
  function doSomething()
  {
    try
    {
      // запрос к базе с ошибкой
    }
    catch (PDOException $e)
    {
      // операции, выполняемые в случае ошибки
      throw new UserException('описание ошибки');
    }
  }
}


Зачастую операции с низкоуровневым классом так или иначе приходится оборачивать в try-catch, т.к. в случае ошибки нужно выполнять какие-то дополнительные операции.
Причем используя класс, построенный таким образом, мы заранее знаем какой именно exeption он может вернуть (например, класс User возвращает только UserException, и никогда не вернет PDOException).
Но есть и недостатки - в итоге мы получаем очень много последовательно выполняющихся блоков try-catch, когда можно было сделать один try снаружи и много блоков catch для каждого типа эксепшенов (если это необходимо). К тому же помимо PDOExeption может произойти ErrorExeption..

И еще момент - передача информации об ошибке пользователю. Допустим User::getUserByEmail('abc') вернет нам UserException "Email is not valid" - как лучше его обработать, чтобы выдать пользователю понятную информацию об ошибке? Хранить массив соответствий errorCode => errorMessage, где errorMessage - понятное описание ошибки на русском языке?

Интересует как вы решаете подобные вопросы и почему именно так?
  • Вопрос задан
  • 2990 просмотров
Подписаться 3 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 1
rumkin
@rumkin
Лишний try-catch это всегда увеличение нагрузки. Поэтому, там, где обертки ради оберток, то лучше убрать. Некторые проекты обходятся несколькими общими классами для ошибок, не по происхождению (это вы в трейсе увидите), а по назначению: ClientException, AppExcetion и CoreException.

Если вы обратили внимание, то широкого распространения наследование исключений не получило.

Сейчас я думаю над моделью схожей с моделью событий в js. В первую очередь классифицирую события по типу, а не по классу-источнику, вместо числового ID (который опять же почти никто не использует), я использую текстовый id, например `user_login_failed` и массив $data c данными. Таким образом, я всегда вижу, что за ошибка пришла, получаю данные в удобном виде: массив $data итерируется и доступен программно, легко перевожу ошибку в сообщение на нужном языке (RU, EN) с подстановкой данных из объекта data, передаю в другие источники, например по сети. Такие данные можно хоть в БД класть :)
Ответ написан
Ваш ответ на вопрос

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

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