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

Обработка исключений с диспетчеризацией?

Я пишу некоторый код на PHP (впрочем вопрос относится к любому языку программирования, поддерживающего исключения). С точки зрения обработки ошибок есть предложение сделать следующим образом:

1) Любые ошибки и предупреждения PHP транслировать в исключения с помощью set_error_handler

2) Кидать собственные исключения в случаях, когда это требуется в силу логики программы

3) Разделить все исключения на фатальные, логгируемые и игнорируемые. К какой категории отнести исключение определяется по типу исключения.

4) В качестве централизованного обработчика исключений через set_error_handler назначить некоторый метод, который будет решать к какой категории относится исключение и выполнять одно из следующих действий:

  а) Для фатальных исключений еще раз кидать его.

  б) Для логгируемых исключений вносить запись в журнал и продолжать работу.

  в) Для игнорируемых исключений просто продолжать работу.

Логика определения типа исключения может быть изменена через конфигурацию программы, поэтому можно сделать все исключения фатальными или же сделать некоторые исключения игнорируемыми. Проблема возникает с продолжением работы. Для того, чтобы любая функция продолжала свою работу после выкидывания исключения нужно везде писать блоки try-catch. При этом теряется смысл назначения централизованного обработчика исключений. Единственный вариант, который я вижу это что-то такое:
function helloWorld(){
    try{
        //Что-нибудь, кидающее исключение
    } catch (Exception $e) {
        Handler::handle($e);
    }
}


Самый главный недостаток этого подхода — усиление жесткости связей в программе. В такой форме класс обработчика придется закодировать во многих местах и при дальнейшем рефакторинге могут возникнуть проблемы. Есть ли у кого идеи как можно решить подобную задачу? А может быть дело в неправильном подходе к исключениям? Тогда как еще сделать подобную централизованную обработку всех ошибок программы?
  • Вопрос задан
  • 3245 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@MikhailEdoshin
Вообще идея не очень. Одно и тоже исключение в одном случае может быть фатальным, в другом — игнорируемым. (Кстати, еще один вариант обработки — выброс нового исключения.) Записывать исключение в лог или нет больше зависит от режима логирования — при отладке записывать все, при обычной работе записывать только важное. Ну и да, смысл использования исключений теряется, если в каждой функции у вас try/catch.

Обычный подход — функция ловит и обрабатывает только те исключения, которые она реально ожидает и может обработать. Обработать — значит игнорировать (обычно при этом делается что-то еще), или же переопределить и выбросить новое, более точное исключение. Если функция просто пробрасывает исключение выше, то это не обработка, это то же самое, как если бы try/catch вообще не было.

Скажем, одна функция считывает файл; если файла нет, она выбрасывает исключение, потому что она функция простая и ничего умного сделать в этой ситуации не может. А вызывающая функция, возможно, уже может что-то сделать — например, создать новый файл с значениями по умолчанию. Или же переопределить его — не просто «не могу открыть файл», а «не могу инициализировать такой-то плагин, переустановите». Если это некритичный плагин, то у такой функции выше будет еще одна функция, которая обработает и это исключение (игнорирует, но сообщит пользователю).

На самом верху стоит универсальный обработчик, который записывает все исключения, которые до него долетели, и дальше или завершает работу, или, скажем, выводит сообщение для пользователя (хотя не знаю, применимо ли это к PHP).
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@egorinsk
Во-первых, вы путаете в тексте понятия «ошибка PHP» и «исключение». В частности, исключение нельзя проигнорировать и продолжить выполнение программы.

Идея заворачивать все в блоки try/catch — тоже маразм, исключения были прижуманы как раз для ухода от необходимости проверять результат работы всех функций.

Вот, как надо делать правильно:

1) Делаем set_error_handler, который превращает все ошибки/варнинги/нотисы/стрикт стандартс в исключения
2) Ставим error_reporting(-1)
3) Делаем set_exception_handler(), который логгирует исключение (неважных исключений не бывает) и выводит красивую страничку 503 (не на продакшене тут же выводятся детали ошибки).
4) Получаем через некоторое время приложение без ошибок

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

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

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