Действительно ли исключения в php так полезны? - PullRequest
10 голосов
/ 23 августа 2010

3 дня назад я начал переписывать один из моих сценариев в ООП, используя классы в качестве практики, после того, как много читал о преимуществах использования ООП.

Теперь я в замешательстве, должен ли я использовать исключения или нет.Кажется, они делают мою работу тяжелее и дольше.

Мое приложение проверяет, были ли данные отправлены с помощью Ajax-запроса, или нет, а затем использует эту информацию через сценарий.

Проверьте этот пример:

 /*
 * The older way
 */

if($ajaxEnabled) {
    $error = errorWrap('Ajax error');
} else {
    $error = errorWithBackLinkWrap('NoAjax error');
}

function doSomething() {
    if(empty($POST['name'])) {
            die($error);
    }
}

/* 
 * OOP way
 */

class someClass {
    private $_ajaxEnabled;

    public function doSomething() {
        try {
            if(!$this->_isDateValid()) {
                if($this->$_ajaxEnabled) {
                    throw new ajaxException('Ajax error');
                } else {
                    throw new noAjaxException('NOAjaxError');
                }
            }
        } catch(ajaxException $e) {
            echo $e->getErrorMessage();
        } catch(noAjaxException $e) {
            echo $e->getErrorMessage();
        }
    }
}

Этот код предназначен только для демонстрации проблемы, поэтому я знаю, что в нем есть некоторые неопределенные функции:).

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

Теперь, используя исключения, в каждой функции сначала нужно проверить тип соединения, а затем написать 2 функции перехвата для каждого сгенерированного исключения, что приводит к гораздо большему коду.

Я действительно новичок в ООП в php, так что, может быть, есть чище и лучший способ сделать это?

Ответы [ 9 ]

8 голосов
/ 23 августа 2010

Ваш вопрос не редкость, является ли / когда использование исключения иногда философским решением, и многие опытные разработчики не могут обернуть голову вокруг него.

При этом я обнаружил, что перечисление различных свойств каждого способа обработки ошибок позволяет легко выбрать предпочтительный способ:

Код возврата

  • Звонящий может проигнорировать или забыть проверить
  • Вызывающему обычно требуется больше чтения документации, прежде чем он сможет ее использовать (0 означает успех или неудачу?)
  • Уничтожение объекта не гарантируется - все зависит от того, кто звонит, чтобы правильно очистить

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

Исключения

  • Вызывающий не может игнорировать это
  • Вызывающий может все еще подавить его, если он хочет (с пустым try/catch)
  • Уничтожение объектов происходит должным образом - большую часть времени

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

Die

  • Нельзя игнорировать и не подавлять

Когда использовать : Обычно это достаточно очевидно. Вам нужно все, чтобы немедленно остановиться.

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


* * Тысяча сорок-девять (в стороне)

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

Каждый объект или каждая функция в идеале должны выполнять только одну функцию. Если одна функция выводит сообщение об ошибке на экран , а делает свое дело, позже трудно переключиться на DatabaseErrorLogger или TextFileErrorLogger или т. Д. Один из подходов заключается в предоставлении логгера (это называется инъекцией зависимости). Другой способ сделать это - использовать исключение - таким образом, вызывающий абонент может выбрать, какой ErrorLogger использовать.

4 голосов
/ 23 августа 2010

Исключения как механизм обработки ошибок ОЧЕНЬ отличаются по концепции и реализации от кодов возврата функций. Вы не можете / не должны просто отображать одно на другое. Вы должны прочитать и переварить эту статью (а затем еще несколько, включая эту *), прежде чем продолжить.

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

(* Ссылка на CodeProject специфична для .NET, но дайджеста кода немного. Это в основном статья с рекомендациями, легко применимая к любому языку.)

4 голосов
/ 23 августа 2010

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

Исключения составляют ситуации, которые являются исключительными. К сожалению, это не очень просто, так что вы, программист, должны решить, что является исключительным или нет. Я думаю, что хорошее эмпирическое правило:

Избегайте использования исключений для указания условия, которые могут быть разумно ожидается как часть типичного Функционирование метода.

От: http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx

2 голосов
/ 23 августа 2010

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

И вам не нужно иметь блок try / catch на каждом уровне.На самом деле, это плохая практика.Поймайте исключения только в том случае, если вы можете обработать исключение или вам нужно сделать что-то еще, прежде чем разрешить продолжение исключения.Так, например: если вы подключаетесь к удаленному набору веб-сайтов, а первый отказывает.Вы можете поймать исключение для этого и повторить попытку со вторым веб-сайтом.И продолжайте до тех пор, пока у вас не останется больше (в этот момент вы будете выдавать другое исключение, чтобы указать, что ни один веб-сайт не может быть выбран).Другим примером может быть, если вы генерируете изображения.У вас есть метод, который выполняет некоторые вычисления при генерации изображения, которое выдает исключение.Вы захотите перехватить это исключение, чтобы вы могли «очистить» процесс обработки изображений (чтобы сэкономить память и т. Д.), А затем повторно выбросить его, как только закончите: catch (ImageSomethingException $e) { /* Clean up here */ throw $e; } ...

Истинная сила исключений заключается в том, что они позволяют вам обрабатывать ситуации так, как вы хотите (поскольку исключение может просто всплыть наверху программы).Но ловите только те исключения, в которых, как вы знаете, вы можете разобраться с ними (или, по крайней мере, нужно очистить)Вы почти никогда не должны делать print $e->getMessage() внутри рабочего кода.

Лично у меня есть обработчик исключений по умолчанию , который я всегда устанавливаю.По сути, если исключение не обнаружено, оно регистрирует это исключение, а затем генерирует страницу с ошибкой 500.Это позволяет мне сосредоточиться на тех исключениях, с которыми я могу иметь дело в коде, вместо того, чтобы пытаться поймать все (что обычно не является хорошей идеей) ...

Удачи ...

2 голосов
/ 23 августа 2010

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

1 голос
/ 23 августа 2010

Существует ограниченная емкость для большинства процессов разработки - т. Е. Даже там, где возможно предсказать все возможные обстоятельства, в которых может выполняться код (т. Е. Все возможные комбинации входов, все возможные состояния для вспомогательных систем, таких как база данных, DNS, существующие данные). и т.д.) тогда просто не практично иметь дело с каждым сценарием. Использование исключений позволяет:

  1. для объединения серии операций в один объект для определения успеха / неудачи в целом

  2. обработка нескольких различных режимов сбоев с помощью одного бита кода

Так что да - я бы сказал, что обработка исключений является полезной практикой, но не заменой для специфической, разумной и информативной обработки общих сбоев (а типизированные исключения - ИМХО полный оксюморон).

1 голос
/ 23 августа 2010

лично я ненавижу исключения.Я не работаю с ними в моих приложениях.Я предпочитаю функции, возвращающие (и ожидающие) определенные коды состояния и работающие с исправляемыми ошибками на этом уровне.

В действительно исключительных ситуациях (таких как недоступный сервер базы данных, ошибка файлового ввода-вывода и т. Д.), Которые являются неотложной ситуацией, я склонен вызывать и обрабатывать фатальную ошибку.(Завершение работы по-прежнему будет происходить, поэтому любые соединения, которые требуют закрытия и т. Д., Будут обрабатываться до тех пор, пока они помещены в функции деструктора .)

Исключения сторонних библиотек, к которым я стремлюсьпоймать как можно быстрее и разобраться с ними по-своему.

Джоэл Спольски объясняет причины гораздо лучше, чем я, в его пресловутом эссе Исключения .

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

0 голосов
/ 05 ноября 2012

Это разработчики называют .. не обязательно, как сказал kizzx2.Но если вы пишете какой-то класс утилит или библиотек, всегда полезно выбросить исключение, поскольку эта библиотека или утилит могут использоваться другими в будущем.

0 голосов
/ 23 августа 2010

Если все, что вам нужно, это отобразить сообщение об ошибке, почему бы вам не использовать

catch (Exception $e)
{ print ($e->getMessage()); }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...