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, так что, может быть, есть более чистый и лучший способ сделать это?
Ваш вопрос не так уж редок: использовать ли/когда использовать исключение - это иногда философское решение, и многие опытные разработчики не могут разобраться в нем.
Учитывая это, я обнаружил, что перечисление отличительных свойств каждого способа обработки ошибок облегчает выбор предпочтительного способа:
0
успех или неудачу?)Когда использовать: Это довольно очевидно. Используйте коды возврата, когда вы доверяете вызывающей стороне (внутренний код или тривиальные ошибки, которые можно спокойно игнорировать).
try/catch
)Когда использовать: Когда вы не очень доверяете вызывающей стороне (третьей стороне) или вам действительно нужно убедиться, что ваш код ошибки не будет проигнорирован.
Когда использовать: Обычно это достаточно очевидно. Вам нужно, чтобы все немедленно прекратилось.
(В контексте PHP, я не думаю, что это имеет большое значение. Вышеприведенные рекомендации все равно применимы.)
(В сторону)
Обычно очень заманчиво просто написать сообщение об ошибке, когда происходит что-то плохое (особенно если первый язык программирования, который вы изучали - PHP :P). Но если вы действительно хотите понять ООП, это не совсем правильный способ обработки ошибок.
Каждый объект или каждая функция в идеале должны выполнять только одну функцию. Если одна функция пишет ошибку на экран и занимается своими делами, трудно потом переключиться на DatabaseErrorLogger
или TextFileErrorLogger
или т.д. Один из подходов заключается в предоставлении логгера для использования (это называется инъекцией зависимости). Другой способ - использовать исключение - таким образом, вызывающая сторона получает возможность выбирать, какой ErrorLogger
использовать.
Исключения как механизм обработки ошибок ОЧЕНЬ отличаются по концепции и реализации от кодов возврата функций. Вы не можете / не должны просто сопоставлять одно с другим. Вы должны прочитать и усвоить эту статью (а затем еще несколько, включая эту * ), прежде чем продолжить.
Если вы собираетесь отдавать предпочтение исключениям вместо кодов возврата для отчетов / обработки ошибок, то структура вашего кода должна значительно измениться.
(* Ссылка CodeProject специфична для .NET, но в ней мало дайджеста кода. В основном это статья с передовыми практиками, легко применимая к любому языку.)
Полезность исключений заключается не в печати кодов ошибок. Он заключается в обнаружении ошибок, поэтому вы можете попытаться их решить, а не сбоить фейерверком.
Если я понимаю, как вы это делаете, я думаю, что вы делаете это неправильно. Исключения не для ошибок. Они предназначены для исключительных обстоятельств. Ошибки могут означать любое количество вещей (например, пользователь не ввел достаточно длинное имя пользователя в регистрационной форме). Само по себе это не должно быть исключением. Однако вы можете использовать исключение, чтобы показать, что сама регистрация не удалась (в зависимости от ситуации) ...
И вам не нужно иметь блок try / catch на каждом уровне. Фактически, это плохая практика. Перехватывайте исключения только в том случае, если вы либо можете обработать исключение, либо вам нужно сделать что-то еще, прежде чем исключение продолжится. Так, например: если вы подключаетесь к удаленному набору веб-сайтов, и первый не работает. Вы можете поймать исключение для этого и повторить попытку со вторым веб-сайтом. И продолжайте до тех пор, пока у вас больше не останется (в этот момент вы бросите еще одно исключение, чтобы указать, что веб-сайты не могут быть получены). Другой пример: вы создаете изображения. У вас есть метод, который выполняет некоторые вычисления при генерации изображения, которое вызывает исключение. Вам нужно перехватить это исключение, чтобы вы могли «очистить» процесс изображения (для экономии памяти и т. Д.), А затем повторно выбросить его, когда закончите: catch (ImageSomethingException $ e) {/ * Убери здесь * / throw $ e; }
...
Истинная сила исключений заключается в том, что они позволяют вам обрабатывать ситуации, как вы хотите (поскольку исключение может просто всплывать в верхней части программы). Но перехватывайте исключения только в тех случаях, когда вы знаете, что можете с ними справиться (или, по крайней мере, необходимо очистить).Практически никогда не следует выполнять print $ e-> getMessage ()
внутри производственного кода.
Лично у меня есть обработчик исключений по умолчанию , который я всегда устанавливаю. Обычно, если исключение не обнаружено, оно регистрирует это исключение, а затем генерирует страницу с ошибкой 500. Это позволяет мне сосредоточиться на том, с какими исключениями я могу справиться в коде, вместо того, чтобы пытаться уловить все (что обычно не является хорошей идеей) ...
Удачи ...
Возможности большинства процессов разработки ограничены - то есть даже там, где возможно предсказать все возможные обстоятельства, в которых может выполняться код (т.е. все возможные комбинации входных данных, все возможные состояния для поддерживающих систем, таких как база данных, DNS, существующие данные и т. д.), то иметь дело с каждым сценарием просто непрактично. Использование исключений позволяет:
объединить серию операций в одну сущность с целью определения успеха / неудачи в целом
обрабатывать несколько различных режимов отказов с помощью одного бита кода
Так что да - я Я бы сказал, что обработка исключений является полезной практикой, но не заменой для обработки общих режимов отказа специально, разумно и информативно (а типизированные исключения - это ИМХО полный оксюморон).
Лично я ненавижу исключения. Я не работаю с ними в своих приложениях. Я предпочитаю функции, возвращающие (и ожидающие) определенные коды состояния и имеющие дело с исправляемыми ошибками на этом уровне.
В действительно исключительных ситуациях (например, недоступность сервера базы данных, ошибка ввода-вывода файла и т. Д.), Которые являются неотложной, я склонен запускать и обрабатывать фатальную ошибку. (Завершение работы объекта по-прежнему будет происходить, поэтому любые соединения, требующие закрытия и т. Д., Будут обрабатываться, пока они помещены в функции деструктора .)
Исключения сторонних библиотек, которые я стараюсь уловить как как можно быстрее и справляюсь с ними по-своему.
Джоэл Спольски излагает причины намного лучше, чем я, в его печально известном эссе об исключениях .
Обратите внимание, что это одна точка зрения и одна школа мысли. Существует множество отличных программ, обработка ошибок которых полностью основана на исключениях, и это нормально. Ключевым моментом является последовательность: либо вы принимаете дизайнерское решение использовать их, либо нет.
Если все, что вам нужно, это отобразить сообщение об ошибке, почему бы вам не использовать
catch (Exception $e)
{ print ($e->getMessage()); }
Вы не должны использовать исключения, если ваш код может изящно обработать ошибку с помощью оператора if (как вы сделали в своем примере).
Исключения для ситуаций, которые являются исключительными. К сожалению, это не очень просто, так что вам, программисту, решать, что является исключительным, а что нет. Я думаю, что хорошим практическим правилом является:
Избегайте использования исключений для обозначения условия, которые могут быть обоснованно ожидается как часть типичного функционирование метода.
От: http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx