Когда лучше всего использовать исключения в PHP? - PullRequest
3 голосов
/ 27 ноября 2009

Я обычно указываю ошибку в методе, возвращая false, но это не всегда семантически связывает меня (в зависимости от метода, false может быть допустимым возвращением).

Я рассмотрел исключения, и мне интересно, являются ли они универсальным решением для всех? Должен ли я вернуть false, где я еще могу?

Я может полностью упустить смысл, поэтому, пожалуйста, потерпите меня.

// My old way
function getProductById($id) {

    if ( ! is_numeric($id)) {
         return false;     
    }

}

// My consideration
function getProductById($id) {

    if ( ! is_numeric($id)) {
         throw new Exception('The id must be numerical!');     
    }

}

Ответы [ 4 ]

2 голосов
/ 05 октября 2015

Мой ход мыслей таков:

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

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

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

Я бы вернул false или null, если бы все работало как положено (как определено), но процесс просто не нашел подходящего продукта.

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

1 голос
/ 27 ноября 2009

Исключения велики! Позволяет сохранить код обработки ошибок вдали от кода ошибки.

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

Когда я говорю, что это помогает убрать код обработки ошибок от ваших ошибок, учтите это

try {    
    func1($a);  
    func2($b);  
    func3($c);  
} catch (Exception $e) {  
    // error handling here  
}  

Так что вам не нужно проверять каждую функцию на ложное возвращение и действовать на нее.

0 голосов
/ 27 ноября 2009

Согласно Джоэлю Спольски, Исключения не должны использоваться .

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

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

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

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

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

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

0 голосов
/ 27 ноября 2009

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

Но если вы хотите переписать свой код для исключений, имейте в виду, что исключения необычно ресурсоемки в PHP (как во время процессора, так и в памяти). Я хотел бы продемонстрировать на примере: представьте, что есть функция Product::getById($id). Если вы хотите, чтобы эта функция генерировала исключение, если идентификатор не был найден, все в порядке. Но если вы хотите многократно вызывать эту функцию в рамках запроса одной страницы и собирать все несуществующие идентификаторы, вы можете сначала подумать о перехвате исключений в цикле. Это приводит к огромному замедлению. Варианты:

  • Дублируйте код (создайте функцию с именем Product::getByIdWithoutException())
  • создать специальную функцию для этого варианта использования (Product::getAllIds(array $ids)). Это лучшее решение, но не всегда выполнимое (без переписывания большого количества кода, без огромного списка параметров или без использования других лучших практик разработки программного обеспечения и т. Д.).

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

function getById($id, $throwException = true) {
    if (!self::idExists($id)) {
        if ($throwException) {
            throw new IdNotFoundException();
        } else {
            return NULL;
        }
    }
    return self::getByWhereClause('id = ' . self::escape($id), $throwException);
}

Думаю, вы найдете это полезным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...