Когда можно использовать обработку исключений для бизнес-логики? - PullRequest
30 голосов
/ 21 марта 2011

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

try{
  _map.put(myKey, myValue);
} catch(NullPointerException e){
  _map = new HashMap<String, String>();
}

Вместо этого ленивая инициализация должна быть выполнена примерно так:

if(_map == null){
  _map = new HashMap<String, String>();
}
_map.put(myKey, myValue);

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

Ответы [ 5 ]

32 голосов
/ 21 марта 2011

Всякий раз, когда исключение можно ожидать, но его нельзя избежать.

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

При правильно разработанном API это должно сводиться к количеству где-то в диапазоне от «практически никогда» до «никогда».

Я не вижу абсолютно никакой причины использовать обработку исключений как средство нормального управления потоком в коде. Это дорого, трудно читать (просто посмотрите на свой первый пример; я понимаю, что он, вероятно, был написан очень быстро, но когда _map не был инициализирован, в результате получается пустая карта, отбрасывающая запись Вы пытались добавить), и он напичкан кодом бесполезными блоками try-catch, которые могут очень хорошо скрыть real проблемы. Опять же, взяв собственный пример, что если бы вызов _map.add() вызвал бы NullPointerException по какой-то причине , отличающийся , отличным от _map, являющимся null? Внезапно вы молча воссоздаете пустую карту, а не добавляете в нее запись. Что, я уверен, мне и не нужно говорить, может привести к любому количеству ошибок в совершенно не связанных местах кода из-за неожиданного состояния ...

Редактировать: Просто чтобы прояснить, ответ выше написан в контексте Java. Другие языки могут (и, очевидно, могут) отличаться в реализации за счет исключений, но другие пункты все же должны соблюдаться.

11 голосов
/ 21 марта 2011

Создание исключения - относительно дорогая операция в C ++ и чрезвычайно дорогая в Java. Только по соображениям эффективности никогда не имеет смысла избегать явной проверки и вместо этого принимать исключение. Я полагаю, что вы могли бы оправдать это в некоторых редких случаях, когда проверка, будет ли выброшено исключение, очень сложна или почти невозможна, но в противном случае я бы сказал, что ответ «почти никогда».

1 голос
/ 30 июля 2013

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

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

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

В любом случае, здесь нет однозначного ответа, вам нужно взвесить оба подхода, а иногда и объединить их.

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

0 голосов
/ 21 марта 2011

Существует причина, по которой исключения являются объектами. Существует также причина, по которой разработчики языка Java делят все Throwable s на 2 основных типа: проверенные и непроверенные.

это хорошая идея полагаться на исключение происходит наверняка бизнес логика возникнет?

Да. Абсолютно. Вам следует прочитать главу 9 «Эффективной Java, второе издание». Это все там. Красиво объяснил и ждет вас.

0 голосов
/ 21 марта 2011

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

try{
   // register new user
   if(getUser(name) != null)
      throw new MyAppException("Such user already exists");
   //other registration steps......
}catch(MyAppException ex){
   sendMessage(ex.getMessage());
}
...