Это - лучшая практика для попытки - ловят мой весь код PHP или максимально конкретны?

У меня нет многих видов Исключений в моем проекте.
Прямо сейчас (мы используем MVC), у меня есть выгода попытки, охватывающая мой весь код:

try{
   fronController::dispatch($somthing...);
}catch(Exception $E){
  //handle errors
}

Интересно, существует ли серьезное основание использовать блок try-catch в максимально конкретном путь, как я могу или просто сохранить это общим, как это теперь?

15
задан Mitch Dempsey 14 May 2010 в 01:13
поделиться

8 ответов

обычно генерируют локально, а перехватывают глобально, если только обработчик исключений не является специфическим для функции, и в этом случае обрабатывается локально.

 class fooException extends Exception{}

 // DB CLASS

 public function Open(){
    // open DB connection
    ...
    if ($this->Conn->connect_errno) 
      throw new fooException("Could not connect: " . $this->Conn->connect_error);
  }

 // MAIN CLASS

 public final function Main(){
    try{
      // do stuff
    }
    catch(fooException $ex){
       //handle fooExceptions
    }
 }
4
ответ дан 30 November 2019 в 23:53
поделиться

Помните, что исключения предназначены для исключительных случаев. Насколько я понимаю, это происходит, когда ошибка выходит из-под вашего контроля. Например, недопустимые параметры передаются в общедоступную функцию API. , деление на ноль, такие ситуации, как «сетевое соединение потеряно», «файл не найден» ... такого рода вещи.

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

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

Там хорошее обсуждение ее e для C ++, но общие концепции применимы. Я нашел java-руководства по исключениям также очень хорошими.

3
ответ дан 30 November 2019 в 23:53
поделиться

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

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

2
ответ дан 30 November 2019 в 23:53
поделиться

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

Будьте конкретны и охватите все свои базы, где требуется обратная связь и где возможно восстановление.

1
ответ дан 30 November 2019 в 23:53
поделиться

Будьте конкретны и соответствующим образом обрабатывайте определенные ошибки.

0
ответ дан 30 November 2019 в 23:53
поделиться

Идея исключения заключается в том, чтобы функция могла сообщить о неудаче без необходимости возвращать специальные значения. В старом добром PHP единственным способом сообщить о проблеме было возвращение функцией специального значения, например false или -1. Это не очень приятно. Например, предположим, я пишу вариант file_get_contents().

Типичным возвращаемым значением является хэндл - целое положительное число. Однако есть две основные проблемы, с которыми я могу столкнуться: указанный вами файл не найден, или указанный вами файл не доступен для чтения. Чтобы указать на ошибку, я могу вернуть отрицательное число - поскольку хэндлы положительные - которое ассоциируется с конкретной причиной ошибки. Скажем, -1 означает, что файл не найден, а -2 означает, что файл не читается.

Теперь у нас возникает проблема: -1 и -2 по своей сути не означают ничего для того, кто читает код. Чтобы исправить это, мы вводим глобальные константы FILE_NOT_FOUND и FILE_NOT_READABLE. Давайте посмотрим на получившийся код.

<?php

define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);

function my_file_get_contents($file) {
    // blah blah blah
}

$friendListFile = getDefaultFriendListFile();

$result = my_file_get_contents($friendListFile);

if ($result == FILE_NOT_FOUND) {
    deleteFriendListFromMenu();
} elseif ($result == FILE_NOT_READABLE) {
    alertUserAboutPermissionProblem();
} else {
    useFriendList($result);
}

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

$result - это ужасное имя переменной. Имена переменных должны быть описательными и очевидными, например $friendListFile. Настоящее имя для $result - $fileContentsOrErrorCode, которое не только слишком длинное, но и показывает, как мы перегружаем одну переменную двумя значениями. Вы никогда, никогда не захотите, чтобы одни и те же данные означали две вещи. Нам нужны отдельные $errorCode и $fileContents!

Так как же нам обойти эту проблему? Одно из не совсем удачных решений, которое используют некоторые библиотеки PHP, заключается в том, что их my_file_get_contents()-подобные функции возвращают false, если сталкиваются с проблемой. Чтобы определить, в чем на самом деле заключалась проблема, мы вместо этого вызываем my_file_get_contents_getError(). Это почти работает.

define('FILE_OKAY', 0);
define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);

$my_file_get_contents_error = FILE_OKAY;

function my_file_get_contents_getError() {
    // blah blah blah
}

function my_file_get_contents($file) {
    global $my_file_get_contents_error;
    // blah blah blah
    // whoa, an error? return false and store the error code in
    // $my_file_get_contents_error
    // no error? set $my_file_get_contents_error to FILE_OKAY
}

$friendListFile = getDefaultFriendListFile();

$result = my_file_get_contents($friendListFile);

if (my_file_get_contents_getError() == FILE_NOT_FOUND) {
    deleteFriendListFromMenu();
} elseif (my_file_get_contents_getError() == FILE_NOT_READABLE) {
    alertUserAboutPermissionProblem();
} elseif (my_file_get_contents_getError() == FILE_OKAY) {
    useFriendList($result);
} else {
    die('I have no idea what happened. my_file_get_contents_getError() returns '
        . my_file_get_contents_getError()
    );
}

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

Мы по-прежнему не можем назвать $result ничем лучше, чем $fileContentsOrFalseIfError. Эта проблема не была исправлена.

Теперь я устранил одну проблему, которую вы могли заметить в предыдущем примере. Что если мы не охватили все коды ошибок? Если программист решит, что должен быть код -3, мы изначально его не обнаружим! Мы могли бы проверить, является ли $result строкой, чтобы убедиться, что это не код ошибки, но в PHP мы не должны заботиться о типах, верно? Теперь, когда мы можем использовать второе возвращаемое значение из my_file_get_contents_getError(), не проблема включить код успеха.

Теперь появилась совершенно новая проблема. Исправьте одну и найдите еще три, а? Новая проблема заключается в том, что можно сохранить только самый последний код ошибки. Это ужасно хрупко! Если кто-нибудь еще вызовет my_file_get_contents() до того, как вы разберетесь со своим кодом ошибки, его код перезапишет ваш!

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

Подождите! Почему бы нам просто не раздавать идентификаторы вызывающим сторонам? Для того чтобы использовать my_file_get_contents(), вы должны попросить create_my_file_get_contents_handle() дать вам какой-то номер, который будет отличать вас от всех остальных вызывающих. Теперь вы можете вызвать my_file_get_contents($myHandle, $myFile) и код ошибки может быть сохранен в специальном месте специально для вас. Теперь, когда вы вызываете my_file_get_contents_getError($myHandle), вы можете получить доступ к этому специальному месту, получить код ошибки, и никто не наступил вам на пятки.

Эх, но если есть много вызывающих, мы не хотим иметь миллионы бесполезных кодов ошибок, валяющихся повсюду. Лучше попросить пользователей вызывать destroy_my_file_get_contents_handle($myHandle), когда они закончат, чтобы мы могли освободить немного памяти.

Надеюсь, все это кажется вам очень знакомым по старым мантрам PHP.

Это все так безумно, просто сделайте это проще, пожалуйста!

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

Введите исключения!

<?php

class FileNotFoundException extends Exception {}
class FileNotReadableException extends Exception {}

function my_file_get_contents($file) {
    if (!is_file($file)) {
        throw new FileNotFoundException($file);
    } elseif (!is_readable($file)) {
        throw new FileNotReadableException($file);
    } else {
        // blah blah blah
    }
}

$friendListFile = getDefaultFriendListFile();

try {
    $fileContents = my_file_get_contents($friendListFile);
    useFriendList($fileContents);
} catch (FileNotFoundException $e) {
    deleteFriendListFromMenu();
} catch (FileNotReadableException $e) {
    alertUserAboutPermissionProblem();
}

Внезапно наши старые головные боли, связанные со специальными возвращаемыми значениями, ручками и соглашениями о кодировании, были излечены!

Теперь мы действительно можем переименовать $result в $fileContents. Если с my_file_get_contents() возникнет проблема, присвоение прерывается, и мы сразу переходим к соответствующему блоку catch. Только если нет ошибки, мы даже не думаем о том, чтобы присвоить $fileContents значение или вызвать useFriendList().

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

Никаких проблем с памятью! Сборщик мусора с радостью очистит неиспользуемые объекты исключений, даже не задумываясь об этом. При использовании старой системы хэндлов мы должны были помнить о необходимости вручную уничтожить хэндл, чтобы он не затерялся в памяти навсегда.

У исключений есть много других преимуществ и особенностей. Я настоятельно рекомендую обратиться к другим источникам, чтобы узнать о них. Особенно интересно то, как они всплывают в стеке выполнения, пока какой-нибудь вызывающий пользователь не поймает их. Также интересно, как вы можете поймать исключение, попытаться устранить проблему, а затем отбросить исключение, если это не удалось. Не забывайте, что исключения - это объекты! Это дает большую гибкость. Для исключений, которые никто не может поймать, обратитесь к обработчику исключений.

Моим намерением ответить на вопрос было показать, зачем нам нужны исключения. Сделав это, я надеюсь, легко понять, какие проблемы мы можем решить с их помощью.

57
ответ дан 30 November 2019 в 23:53
поделиться

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

Это также хорошая практика как соглашение, особенно если вы позже работаете над командными проектами и не единственный, кто смотрит код.

Собирать все в один блок try catch кажется запахом кода .

3
ответ дан 30 November 2019 в 23:53
поделиться

Для разных ошибок могут потребоваться разные ответы.

Вы бы не выпрыгнули из самолета в ответ на любую возможную проблему, которая может возникнуть. Не могли бы вы?

Что ж, это то, что делает ваше приложение.

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

1
ответ дан 30 November 2019 в 23:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: