Исключения: это хорошая практика? - PullRequest
1 голос
/ 19 сентября 2008

Это написано на 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 Issue выдает исключение, если возникает ошибка, и я считаю, что это хороший способ обнаружения ошибок.

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

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

Спасибо

Ответы [ 7 ]

10 голосов
/ 19 сентября 2008

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

2 голосов
/ 19 сентября 2008

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

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

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

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

2 голосов
/ 19 сентября 2008

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

try{
  Something();
}
catch( SpecificException se )
{blah();}
catch( AnotherException ae )
{blah();}
0 голосов
/ 20 сентября 2008

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

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

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

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

0 голосов
/ 19 сентября 2008

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

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

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

0 голосов
/ 19 сентября 2008

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

...