1

Это написано на 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); 
} 

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

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

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

Благодаря

+0

О, и измените заголовок сообщения, чтобы лучше отразить тему; «Это хорошая практика» на самом деле не описательна. Как насчет «Исключения: вложенные блоки try/catch?» – Aeon 2008-09-19 17:29:22

ответ

10

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

2

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

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

Проблема с множеством уловов в этом случае заключается в том, что я могу поймать DM_Exception ИЛИ Error_Page - это не то, что я хочу сделать. – Ross 2008-09-19 16:57:36

+0

Если вы поймаете конкретное исключение, которое хотите передать, просто используйте throw; (который просто перебрасывает исключение) или бросает новое MyException («Вот моя ошибка», innerException) (который создает новое исключение и строит трассировку стека с innerException). – 2008-10-02 13:02:32

0

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

+0

Я думаю, это зависит от языка. Я точно знаю, что в Java вы можете «цепочки» исключений, чтобы вы не потеряли исходную стекловидную структуру при повторном перевороте. – 2008-09-19 16:51:05

0

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

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

2

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

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

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

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

0

Я бы не бросить исключение на вопрос не найден - это действительное состояние приложения, и вам не нужно трассировки стека только для отображения 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. 
} 
0

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

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

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

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