Преобразование ошибок в исключения: ошибка дизайна?

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

class AppException extends Exception { } function error_handler($errno, $errstr, $errfile, $errline) { throw new AppException($errstr, $errno); } function exception_handler($exception) { $min = ...; $max = ...; if ($exception->getCode() >= $min && $exception->getCode() <= $max) { // log exception } } set_error_handler('error_handler'); set_exception_handler('exception_handler'); $a[1]; // throws exception 

Проблема в том, что я видел такие вещи, как:

 try { do_something(); } catch (AppException $exception) { } 

Это подразумевает отсутствие различий между фактическими ошибками программирования и «исключительным» поведением. После дальнейшего копания я наткнулся на части кода, которые были разработаны вокруг идеи о том, что ошибки PHP представляют собой «исключительное» поведение, такое как:

 ... function my_function($param1, $param2) { // do something great } try { my_function('only_one_param'); } catch (AppException $exception) { } 

Который заканчивается запутыванием ошибок и дизайном интерфейса приложения.

Каково ваше мнение об обработке ошибок таким образом? Стоит ли превращать собственные ошибки PHP в исключения? Что вы делаете в ситуациях, подобных описанным выше, где создается кодовая база вокруг этой идеи?

    Лично я делаю это все время. Единственное различие заключается в том, что в моей функции error_handler я проверяю, error_handler ли ошибка является E_NOTICE , и только бросайте, если это не так (я регистрирую уведомление в любом случае) …

    Я бы изменил AppException на то, что расширяет ErrorException … Что-то вроде: PhpRuntimeErrorException extends ErrorException которое вы используете только для ошибок PHP … Причина в том, что это более читаемо (проще сказать, что PhpRuntimeErrorException не нужно где его бросают). Другая причина заключается в том, что ErrorException будет хранить информацию генерирующей строки / файла / etc, где она не будет храниться в другом месте (поскольку обратная трассировка начинается с линии throw ) …

    Итак, вы можете «попробовать» код следующим образом:

     try { $f = fopen('foo.bar', 'r'); $ret = ''; while ($data = fread($f)) { $ret .= process($data); } fclose($f); return ''; } catch (PHPRuntimeErrorException $e) { throw new RuntimeException('Could not open file'); } catch (ProcessException $e) { fclose($f); throw new RuntimeException('Could not process data'); } return $ret; 

    Я также создаю обработчик исключения по умолчанию, создающий страницу ошибок сервера 500. Это потому, что любые исключения должны быть пойманы, а если они не были, это действительно ошибка сервера …

    Только мой опыт и мнение …

    В сообществе PHP были некоторые споры об этом. Я считаю, что общее мышление состоит в том, что ошибки – это вещи, которые бросают внутренние функции PHP, и представляют собой проблемы с кодированием, которые вам действительно нужно исправить; в то время как исключения – это вещи, брошенные вашим кодом приложения, которые вам просто нужно «обрабатывать».

    Однако некоторые из новых расширений SPL (которые, как правило, более объектно-ориентированные) используют исключения для вещей, которые ранее могут быть вызваны ошибками, поэтому существует некоторая серая область.

    Существует также основной класс PHP ErrorException – http://www.php.net/manual/en/class.errorexception.php, который выглядит немного проще в использовании, чем пример вашего кода, если это маршрут, по которому вы хотите спуститься.

    Я конвертирую все, включая уведомления об исключениях. Нет никаких оснований позволять исключениям продолжать нормально, как это происходит. Неопределенная переменная или смещение? Это проблема.

    https://github.com/KyleWolfe/PHPErrorNet