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

Является ли хорошей практикой использование вложенных исключений?

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

Я просматривал какой-то старый код и нашел его часть, у которой есть методы с исключениями, вложенными в 3 или 4 уровня вниз.
Является ли это обычной практикой или следует избегать такого кодешина, где это возможно? Если этого следует избегать, каковы негативные последствия, помимо увеличения затрат на обработку исключений и снижения удобочитаемости? Существуют ли общие способы рефакторинга кода, чтобы избежать этого?

4b9b3361

Ответ 1

Я лично предпочитаю следующую идеологию

Исключение Wrap Alien

Исключением "чужое" является исключение, созданное Java API или сторонней библиотекой. Другими словами, исключение, которое вы не контролируете.

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

Повторная проверка Проверенные исключения могут стать Messy

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

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

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

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

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

public void doSomething() throws SomeException{

    try{

        doSomethingThatCanThrowException();

    } catch (SomeException e){

       e.addContextInformation("more info");
       throw e;  //throw e, or wrap it – see next line.

       //throw new WrappingException(e, "more information");

    } finally {
       //clean up – close open resources etc.
    }

}

Ответ 2

Обработка исключений имеет тенденцию быть дорогостоящим способом управления потоком (конечно, для С# и Java).

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

Все это стоит в памяти и ресурсах ЦП, которые не нужно расширять, если операторы управления потоком используются для управления потоком.

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

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

Пожалуйста, взгляните ниже ссылки

Обработка исключений: общие проблемы и передовая практика с Java 1.4 - pdf

Почему бы не использовать исключения в качестве регулярного потока управления?

Рекомендации по обработке исключений

Обработка ошибок

Mr. Ссылки Google

Ответ 3

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

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

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

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

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

Существуют ли общие способы рефакторинга кода, чтобы избежать этого?

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

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

Хоп это поможет вам.

Ответ 4

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

В трехслойном примере: Дао, Сервис, Контроллер

Уровень DAO будет вызывать DAOException Сервисный уровень не должен подвергать DAOException контроллеру, вместо этого он должен бросать соответствующие BuinessExceptions, над которыми должен работать контроллер.

Ответ 5

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

Ответ 6

О обработке устаревшего кода Я бы порекомендовал вам ознакомиться с книгой, посвященной теме: http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 Вам даже не нужно проходить через всю книгу, просто посмотрите на то, что вас беспокоит в данный момент.

Также хорошая книга о передовом опыте: http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?s=books&ie=UTF8& QID = 1356340809 & ср = 1-1 & ключевые слова = чистый + код

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

Ответ 7

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

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

e.q. oracle JDBC. Driver.getConnection() выдает исключение. Теперь пользователь caller/API может обрабатывать его в соответствии с их потребностями. Можно просто распечатать трассировку стека, можно предупредить администратора, обратившись за его вниманием, или вы можете просто молча выйти из приложения.

Ответ 8

Существует два подхода:

To generate a separate exception for each event.
To create a generic exception and describe what caused it 

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

Второй подход более краткий, но он затрудняет обработку различных ситуаций.

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

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

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

Единый блок блокировки для всех. Например:

catch (Throwable e) {
throw new CommandExecutorException(e);
}

много блоков catch по одному для каждого исключения. Например:

} catch (ClassCastException e1) {
 ...
} catch (FileNotFoundException e) {
... 
} catch (IOException e) {
...
}

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

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