Вопрос

Это написано на 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 хорошей практикой для подражания?Это кажется немного громоздким только для страницы с ошибкой - однако мой Issue 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 DM_Exception.Но для реального приложения я одобряю принцип не умирать просто так у черта на куличках.

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top