Действительно ли полезны исключения в php?

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, так что, может быть, есть более чистый и лучший способ сделать это?

10
задан Daniel Vandersluis 23 August 2010 в 16:04
поделиться

8 ответов

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

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

Код возврата

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

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

Исключения

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

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

Умереть

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

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

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


(В сторону)

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

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

8
ответ дан 3 December 2019 в 17:56
поделиться

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

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

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

4
ответ дан 3 December 2019 в 17:56
поделиться

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

2
ответ дан 3 December 2019 в 17:56
поделиться

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

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

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

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

Удачи ...

2
ответ дан 3 December 2019 в 17:56
поделиться

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

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

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

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

1
ответ дан 3 December 2019 в 17:56
поделиться

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

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

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

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

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

1
ответ дан 3 December 2019 в 17:56
поделиться

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

catch (Exception $e)
{ print ($e->getMessage()); }
0
ответ дан 3 December 2019 в 17:56
поделиться

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

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

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

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

4
ответ дан 3 December 2019 в 17:56
поделиться
Другие вопросы по тегам:

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