Исключения: Это хорошая практика?

Это написано на PHP, но на самом деле это язык агностик.

try { try { $issue = new DM_Issue($core->db->escape_string($_GET['issue'])); } catch(DM_Exception $e) { throw new Error_Page($tpl, ERR_NOT_FOUND, $e->getMessage()); } } catch(Error_Page $e) { die($e); } 

Является ли вложенный try, catch блоки хорошей практикой следовать? Это кажется немного громоздким только для страницы с ошибкой – однако мой выпуск Datamanager выбрасывает исключение, если возникает ошибка, и я считаю, что это хороший способ обнаружения ошибок.

Исключение Error_Page – это просто компилятор страницы с ошибкой.

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

благодаря

Вы используете Исключения для логики страницы, и я лично считаю, что это нехорошо. Исключения должны использоваться, чтобы сигнализировать о том, когда происходят плохие или неожиданные события, а не контролировать вывод страницы с ошибкой. Если вы хотите создать страницу с ошибкой на основе Исключения, рассмотрите возможность использования set_exception_handler . Любые неперехваченные исключения выполняются с помощью любого метода обратного вызова, который вы указываете. Имейте в виду, что это не останавливает «фатальность» Исключения. После того как исключение будет передано через ваш обратный вызов, выполнение прекратится, как обычно, после любого неперехваченного исключения.

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

 try{ Something(); } catch( SpecificException se ) {blah();} catch( AnotherException ae ) {blah();} 

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

Итак, если $ tpl и ERR_NOT_FOUND – это информация, которая только «известна» рядом с новым вызовом DM_Issue, например, потому что есть другие места, где вы создаете DM_Issue, и хотите, чтобы ERR_SOMETHING_ELSE, или потому что значение $ tpl варьируется, тогда вы «перехватывает первое исключение в нужном месте.

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

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

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

Я не уверен в PHP, но, например, на C # у вас может быть больше одного блока catch-block, поэтому нет необходимости в вложенных комбинациях try / catch.

Вообще, я считаю, что обработка ошибок с помощью try / catch / наконец-то всегда является здравым смыслом, а также для отображения «только» страницы с ошибкой. Это чистый способ справиться с ошибками и избежать странного поведения при сбое.

Я бы не выбрал исключение по проблеме не найденное – это действительное состояние приложения, и вам не нужна трассировка стека, чтобы отобразить 404.

То, что вам нужно поймать, – это непредвиденные сбои, такие как ошибки sql – вот почему обработка исключений пригодится. Я бы изменил ваш код, чтобы он выглядел следующим образом:

 try { $issue = DM_Issue::fetch($core->db->escape_string($_GET['issue'])); } catch (SQLException $e) { log_error('SQL Error: DM_Issue::fetch()', $e->get_message()); } catch (Exception $e) { log_error('Exception: DM_Issue::fetch()', $e->get_message()); } if(!$issue) { display_error_page($tpl, ERR_NOT_FOUND); } else { // ... do stuff with $issue object. } 

Исключения должны использоваться только в том случае, если существует потенциально уязвимое событие – например, запрос базы данных не выполняется должным образом или что-то неправильно сконфигурировано. Хорошим примером является то, что каталог кэша или журнала не доступен для записи в процессе Apache.

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

Итак, нет; Вложенные обработчики захвата не являются хорошей идеей. На моих страницах мой файл index.php обертывает свой код в блоке try … cache – и если что-то плохое происходит, он проверяет, не является ли его производство или нет; и либо отправляет мне электронную почту, либо отображает общую страницу ошибок, либо показывает ошибку прямо на экране.

Помните: PHP не является C #. C # (с исключением (hehe, no pun предназначено: p) ASP.net) для приложений, которые содержат состояние, тогда как PHP – это язык сценариев без состояния.