Подтвердить что ты не робот

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

Я думаю, что считается, что в качестве общего правила на 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?

4b9b3361

Ответ 1

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

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

С правильно спроектированным API это должно сводиться к количеству где-то в диапазоне "практически никогда" до "никогда".

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

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

Ответ 2

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

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Да. Абсолютно. Вы должны прочитать Глава 9 "Эффективная Java, второе издание". Это все. Красиво объяснили и ждали вас.

Ответ 5

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

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