Когда можно использовать обработку исключений для бизнес-логики?
Я думаю, что принято считать, что в качестве общего правила на Java (и, возможно, на любом языке с обработкой исключений) следует попытаться избежать использования обработки исключений, чтобы фактически обрабатывать бизнес-логику. В общем, если ожидается, что определенная ситуация должна произойти, нужно проверить ее и обработать ее более непосредственно, чем полагаться на обработку исключений, чтобы выполнить проверку для вас. Например, следующая практика не считается хорошей практикой:
try{ _map.put(myKey, myValue); } catch(NullPointerException e){ _map = new HashMap(); }
Вместо этого ленивая инициализация должна выполняться следующим образом:
if(_map == null){ _map = new HashMap(); } _map.put(myKey, myValue);
Конечно, может быть гораздо более сложная логика, чем просто обработка ленивой инициализации. Поэтому, учитывая, что этот тип вещей обычно неодобрительно … когда, если вообще когда-либо, есть ли хорошая идея полагаться на исключение, происходящее для определенной бизнес-логики? Было бы правильным сказать, что любой случай, когда вы чувствуете себя вынужденным использовать этот подход, действительно подчеркивает слабость используемого API?
- Проверка указателя NULL в C / C ++
- Не удается получить доступ к родительским элементам при работе с аннотациями макросов
- «Взаимодействие с пользователем не разрешено», пытаясь подписать приложение OSX с использованием кода
- Файлы заголовков C ++, разделение кода
- Codesign API Dropbox не работает в Xcode 4.6.3: «Объект кода вообще не подписан»
- В чем разница между собственным кодом, машинным кодом и кодом сборки?
- Отладчик Visual Studio - отображение целочисленных значений в шестнадцатеричном виде
- Как получить «кодовое обозначение» gdb на OSX?
- Ошибка кодового знака: профиль Provisioning не найден.
- Что означает == $ 0 (double equals dollar zero) в инструментах разработчика Chrome?
- Покрытие кода, не показывающее результаты с помощью Xcode + gcov
- Подписывание ароматов продуктов с gradleиентом
- Завершение кода PHP NetBeans
Всякий раз, когда исключение можно ожидать, но не избегать.
Скажем, если вы полагаетесь на внешний API какого-то типа для анализа данных и что API предлагает методы анализа, но нечего сказать, может ли данный вход обрабатываться или нет (или если результат анализа может быть успешным или нет, зависит от факторов вашего управления, но API не предоставляет соответствующие вызовы функций), а метод синтаксического анализа генерирует исключение, когда вход не может быть проанализирован.
При правильно спроектированном API это должно сводиться к количеству где-то в диапазоне «практически никогда» до «никогда».
Я не вижу абсолютно никакой причины использовать обработку исключений как средство нормального управления streamом в коде. Это дорого, трудно читать (просто посмотрите на свой собственный первый пример, я понимаю, что он, вероятно, был написан очень быстро, но когда _map
не был инициализирован, то, что у вас получается, – это пустая карта, отбрасывающая запись, пытаясь добавить), и он помещает код с бесполезными блоками try-catch, которые могут очень скрыть настоящие проблемы. Опять же, взяв ваш собственный пример, что если вызов _map.add()
был вызывать _map.add()
NullPointerException
по какой-то причине, кроме _map
являющейся null
? Внезапно вы тихо воссоздаете пустую карту, а не добавляете в нее запись. Я уверен, что я действительно не могу сказать, может привести к количеству ошибок в совершенно несвязанных местах в коде из-за неожиданного состояния …
Редактирование: просто чтобы быть ясным, вышеупомянутый ответ написан в контексте Java. Другие языки могут (и, по-видимому, делать) различать затраты на выполнение исключений, но другие пункты должны по-прежнему сохраняться.
Выброс исключения – относительно дорогостоящая операция на C ++ и чрезвычайно дорогая в Java. Только по соображениям эффективности никогда не имеет смысла избегать явной проверки и вместо этого принимать исключение. Я полагаю, вы могли бы оправдать его в некоторых редких случаях, когда проверка того, будет ли выбрано исключение, очень сложна или почти невозможна, но в остальном я бы сказал, что ответ «почти никогда».
Это действительно вопрос для обсуждения, и ответ зависит от дизайна вашей системы.
Мой инстинкт никогда не бывает одеялом, но я видел, как несколько систем применяют бизнес-ошибки с использованием исключений. Я лично считаю это отвратительным, но я действительно понимаю преимущество взлома бизнес-процесса, как только вы знаете, что он не справился, справлялся с вашей неудачей (например, откатывал свой блок работы) и возвращал ошибку вызывающему, возможно, с добавлением Информация.
одним из возможных недостатков является то, что очень просто выполнять обработку ошибок в нескольких разных classах, так что определение того, что происходит, когда процесс выходит из строя, действительно сложно вывести из кода.
Во всяком случае, здесь нет единого ответа, вам нужно взвесить оба подхода, а иногда и комбинировать их.
в отношении вашего примера я не вижу никаких преимуществ для использования исключений для управления streamом, особенно в сценарии «хороший» (для работы).
Исключение составляют исключения. Существует также причина, по которой разработчики языка Java разбивают все Throwable
на два основных типа: проверены и не Throwable
.
это хорошая идея полагаться на исключение, происходящее для определенной бизнес-логики?
Да. Абсолютно. Вы должны прочитать главу 9 «Эффективная Java, второе издание». Это все. Красиво объяснили и ждут вас.
Если вы имеете дело с условием ошибки, которое фактически является частью бизнес-логики, вполне нормально использовать Исключения. Например:
try{ // register new user if(getUser(name) != null) throw new MyAppException("Such user already exists"); //other registration steps...... }catch(MyAppException ex){ sendMessage(ex.getMessage()); }