Я прочитал некоторый код коллеги и обнаружил, что он часто перехватывает различные исключения, а затем всегда выдает «RuntimeException». Я всегда думал, что это очень плохая практика. Я ошибаюсь?
java
exceptions
exception-handling
RoflcoptrException
источник
источник
Function
,Predicate
и т.д.) не имеют параметризованные броски положения. Это означает, что вам нужно перехватывать, переносить и перебрасывать любые проверенные исключения во внутреннем цикле любых методов stream (). Это само по себе помогает мне понять, являются ли проверенные исключения плохой идеей.Ответы:
Я не знаю достаточно контекста, чтобы знать, что ваш коллега делает что-то неправильно или нет, поэтому я собираюсь спорить об этом в общем смысле.
Я не думаю, что всегда является неправильной практикой превращать проверенные исключения в некую разновидность исключений во время выполнения . Проверяемые исключения являются часто злоупотребляли и злоупотребляют разработчиками.
Проверенные исключения очень легко использовать, когда они не предназначены для использования (неисправимые условия или даже поток управления). Особенно, если проверенное исключение используется для условий, из которых вызывающая сторона не может восстановиться, я думаю, что было бы оправданным превратить это исключение в исключение времени выполнения с полезным сообщением / состоянием. К сожалению, во многих случаях, когда кто-то сталкивается с неисправимым состоянием, у него, как правило, есть пустой блок catch, что является одним из худших действий, которые вы можете сделать. Отладка такой проблемы - одна из самых больших проблем, с которой может столкнуться разработчик.
Поэтому, если вы считаете, что имеете дело с восстанавливаемым условием, оно должно обрабатываться соответствующим образом, и исключение не должно превращаться в исключение времени выполнения. Если для невосстановимых условий используется проверенное исключение, его превращение в исключение времени выполнения оправдано .
источник
Это может быть ХОРОШО . Пожалуйста, прочитайте:
http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html
Бросать проверенные исключения и неспособность восстановиться после этого не помогает.
Некоторые люди даже думают, что проверенные исключения не должны использоваться вообще. См. Http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html.
Также по той же ссылке:
источник
Нет, вы не ошиблись. Его практика крайне ошибочна. Вы должны выдать исключение, которое фиксирует проблему, вызвавшую его. RunTimeException является широким и исчерпывающим. Это должно быть NullPointerException, ArgumentException и т. Д. Независимо от того, что точно описывает, что пошло не так. Это дает возможность дифференцировать проблемы, которые вы должны решить, и позволить программе выживать в сравнении с ошибками, которые должны быть в сценарии «Не проходить». То, что он делает, лишь немного лучше, чем «При ошибке продолжить далее», если в информации, представленной в вопросе, чего-то не хватает.
источник
По-разному.
Эта практика может быть даже мудрой . Существует много ситуаций (например, при веб-разработке), когда, если возникает какое-то исключение, вы не можете ничего сделать (потому что вы не можете, например, восстановить несогласованную БД из своего кода :-), это может сделать только разработчик). В этих ситуациях целесообразно превратить выброшенное исключение в исключение времени выполнения и перебросить его. Чем вы можете перехватить все эти исключения в каком-либо слое обработки исключений, зарегистрировать ошибку и отобразить пользователю какой-нибудь красивый локализованный код ошибки + сообщение.
С другой стороны , если исключение не является средой выполнения (проверено), разработчик API указывает, что это исключение разрешимо и должно быть исправлено. Если это возможно, то вы обязательно должны это сделать.
Другое решение может заключаться в том, чтобы перебросить это проверенное исключение в вызывающий слой, но если вы не смогли его решить, где произошло исключение, вы, вероятно, не сможете решить его и здесь ...
источник
exception handling layer
- например, в веб-приложении, фильтра.Я хотел бы получить комментарии по этому поводу, но я нахожу, что бывают случаи, когда это не обязательно является плохой практикой. (Или ужасно плохо). Но, возможно, я ошибаюсь.
Часто используемый вами API генерирует исключение, которое вы не можете себе представить, чтобы его на самом деле бросали в вашем конкретном случае использования. В этом случае кажется вполне подходящим генерировать исключение RuntimeException с перехваченным исключением в качестве причины. Если выдается это исключение, оно, скорее всего, станет причиной ошибки программирования и не будет в рамках правильной спецификации.
Предполагая, что RuntimeException позже не перехватывается и не игнорируется, его нет рядом с OnErrorResumeNext.
OnErrorResumeNext возникает, когда кто-то перехватывает исключение и просто игнорирует его или просто распечатывает. Это ужасно плохая практика почти во всех случаях.
источник
TL; DR
посылка
Заключение
Мы можем перебросить проверенное исключение как исключение времени выполнения, если распространяющийся или интерфейсный код предполагает, что базовая реализация зависит от внешнего состояния, а это явно не так.
В этом разделе обсуждается тема, когда должно быть выброшено одно из исключений. Вы можете перейти к следующей горизонтальной полосе, если хотите просто прочитать более подробное объяснение заключения.
Когда уместно выдать исключение времени выполнения? Вы генерируете исключение времени выполнения, когда становится ясно, что код неверен и что восстановление целесообразно путем изменения кода.
Например, целесообразно выдать исключение времени выполнения для следующего:
Это создаст деление на ноль исключений времени выполнения. Это уместно, потому что код неисправен.
Или, например, вот часть
HashMap
конструктора:Чтобы зафиксировать начальную емкость или коэффициент загрузки, целесообразно отредактировать код, чтобы убедиться, что в него передаются правильные значения. Это не зависит от того, работает ли какой-нибудь удаленный сервер, от текущего состояния диска, файл или другая программа. То, что конструктор вызывается с недопустимыми аргументами, зависит от правильности вызывающего кода, будь то неправильное вычисление, которое привело к неверным параметрам или неуместному потоку, который пропустил ошибку.
Когда уместно бросить проверенное исключение? Вы генерируете проверенное исключение, когда проблема может быть исправлена без изменения кода. Или, говоря другими словами, вы генерируете проверенное исключение, когда ошибка связана с состоянием, а код верен.
Теперь слово «выздоровление» здесь может быть хитрым. Это может означать, что вы найдете другой способ достижения цели: например, если сервер не отвечает, вам следует попробовать следующий сервер. Если такое восстановление возможно для вашего случая, то это замечательно, но это не единственное, что означает восстановление - восстановление может просто отображать диалоговое окно с сообщением об ошибке, объясняющее, что произошло, или, если это серверное приложение, то это может быть отправив электронное письмо администратору или даже просто записав ошибку надлежащим образом и кратко.
Давайте возьмем пример, который был упомянут в ответе mrmuggles:
Это не правильный способ обработки проверенного исключения. Простая неспособность обработать исключение в области действия этого метода не означает, что приложение должно быть аварийно завершено. Вместо этого целесообразно распространить его на более высокую область, например:
Что учитывает возможность восстановления абонентом:
Проверенные исключения являются инструментом статического анализа, они дают понять программисту, что может пойти не так в определенном вызове, не требуя от них изучения реализации или прохождения процесса проб и ошибок. Это позволяет легко гарантировать, что никакие части потока ошибок не будут проигнорированы. Возврат проверенного исключения в качестве исключения времени выполнения работает с этой трудоемкой функцией статического анализа.
Также стоит упомянуть, что вызывающий уровень имеет лучший контекст более сложной схемы вещей, как было продемонстрировано выше. Причин для этого может быть много
dataAccessCode
, конкретная причина вызова видна только вызывающей стороне - таким образом, он может принять лучшее решение при правильном восстановлении после сбоя.Теперь, когда мы разобрались с этим различием, мы можем перейти к выводу, когда можно перебросить проверенное исключение как исключение времени выполнения.
Учитывая вышесказанное, когда уместно выбрасывать проверенное исключение как RuntimeException? Когда используемый вами код предполагает зависимость от внешнего состояния, но вы можете четко утверждать, что он не зависит от внешнего состояния.
Учтите следующее:
В этом примере код распространяется,
IOException
потому что APIReader
предназначен для доступа к внешнему состоянию, однако мы знаем, чтоStringReader
реализация не имеет доступа к внешнему состоянию. В этой области, где мы, безусловно, можем утверждать, что части, участвующие в вызове, не обращаются к IO или любому другому внешнему состоянию, мы можем безопасно перевести исключение в качестве исключения времени выполнения без удивительных коллег, которые не знают о нашей реализации (и, возможно, при условии, что код доступа к IO выдаетIOException
).Причина строгой проверки внешних зависимых от состояния исключений заключается в том, что они недетерминированы (в отличие от логически зависимых исключений, которые будут предсказуемо воспроизводиться каждый раз для версии кода). Например, если вы попытаетесь разделить на 0, вы всегда получите исключение. Если вы не разделите на 0, вы никогда не создадите исключение, и вам не нужно обрабатывать этот случай исключения, потому что это никогда не произойдет. В случае доступа к файлу, однако, одноразовое выполнение не означает, что вы добьетесь успеха в следующий раз - пользователь мог изменить разрешения, другой процесс мог удалить или изменить его. Таким образом, вы всегда должны обрабатывать этот исключительный случай, или у вас, вероятно, есть ошибка.
источник
Для автономных приложений. Когда вы знаете, что ваше приложение не может обработать исключение, вы могли бы вместо того, чтобы выдавать проверенное RuntimeException, генерировать Error, позволить аварийному завершению приложения, надеяться на сообщения об ошибках и исправлять ваше приложение. (См ответ на mrmuggles для более глубокого обсуждения про и против сдаваемого против бесконтрольно.)
источник
Это обычная практика во многих рамках. Например
Hibernate
, именно это. Идея состоит в том, что API не должны быть навязчивыми для клиентской стороны иException
навязчивыми, поскольку вы должны явно написать код для обработки их в том месте, где вы вызываете API. Но это место может быть не лучшим местом для обработки исключения в первую очередь.На самом деле, если честно, это «горячая» тема, и многие спорят, поэтому я не буду принимать сторону, но скажу, что то, что делает / предлагает ваш друг, не является чем-то необычным или необычным.
источник
Вся вещь с «проверенным исключением» - плохая идея.
Структурное программирование позволяет передавать информацию только между функциями (или, на языке Java, методами), когда они «рядом». Точнее говоря, информация может перемещаться между функциями только двумя способами:
От вызывающего к вызываемому через передачу аргументов.
От вызываемого до вызывающего, в качестве возвращаемых значений.
Это принципиально хорошая вещь. Это то, что позволяет вам рассуждать о вашем коде локально: если вам нужно понять или изменить часть вашей программы, вам нужно только взглянуть на эту часть и другие «близлежащие».
Однако в некоторых обстоятельствах необходимо отправлять информацию в «отдаленную» функцию, чтобы никому из «посредников» не было «известно». Именно тогда должны быть использованы исключения. Исключением является секретное сообщение, отправляемое от сборщика (любая часть вашего кода может содержать
throw
инструкцию) обработчику (любая часть вашего кода может содержатьcatch
блок, совместимый с исключением, которое былоthrow
n).Проверенные исключения разрушают секретность механизма, а вместе с ним и саму причину его существования. Если функция может позволить своему вызывающему «знать» часть информации, просто отправьте эту часть информации непосредственно как часть возвращаемого значения.
источник
Это может зависеть от случая к случаю. В определенных сценариях целесообразно делать то, что делает ваш друг, например, когда вы выставляете API для некоторых клиентов и хотите, чтобы клиент меньше всего знал о деталях реализации, когда вы знаете, что определенные исключения реализации могут быть специфичны для детали реализации и не подлежат представлению клиенту.
Сохраняя проверенные исключения, вы можете предоставить API, которые позволят клиенту писать более чистый код, поскольку сам клиент может предварительно проверять исключительные условия.
Например, Integer.parseInt (String) принимает строку и возвращает ее целочисленный эквивалент и выдает исключение NumberFormatException, если строка не является числовой. Теперь представьте, что отправка формы с полем
age
преобразуется с помощью этого метода, но клиент уже обеспечил бы проверку со своей стороны, поэтому нет смысла принудительно проверять исключение.источник
Здесь действительно есть пара вопросов
Общее эмпирическое правило заключается в том, что следует проверять исключения, от которых ожидается, что вызывающий абонент поймает и восстановится. Другие исключения (в тех случаях, когда единственным разумным результатом является прерывание всей операции или если вы считаете их достаточно маловероятными, если беспокоиться о том, чтобы обрабатывать их конкретно, не стоит), следует не проверять.
Иногда ваше мнение о том, заслуживает ли исключение перехват и восстановление, отличается от того API, с которым вы работаете. Иногда контекст имеет значение, исключение, которое стоит обработать в одной ситуации, может не стоить обрабатывать в другой. Иногда ваша рука вынуждена существующими интерфейсами. Так что да, есть законные причины, чтобы превратить проверенное исключение в непроверенное исключение (или в другой тип проверенного исключения)
Прежде всего, и самое главное, убедитесь, что вы используете механизм цепочки исключений. Таким образом, информация из исходного исключения не теряется и может быть использована для отладки.
Во-вторых, вы должны решить, какой тип исключения использовать. Использование простого исключения времени выполнения усложняет для вызывающей стороны определить, что пошло не так, но если вызывающая сторона пытается определить, что пошло не так, это может указывать на то, что вы не должны были изменять исключение, чтобы сделать его неконтролируемым.
источник
В булевом вопросе трудно ответить по-разному после двух спорных ответов, но я хотел бы дать вам точку зрения, которая даже упоминалась в нескольких местах, она не была подчеркнута настолько, насколько это важно.
С годами я обнаружил, что всегда кто-то смущается из-за тривиальной проблемы, ему не хватает понимания некоторых основ.
Расслоение. Программное приложение (по крайней мере, должно быть) куча слоев один поверх другого. Одним из важных ожиданий хорошего наслоения является то, что нижние уровни обеспечивают функциональность для потенциально нескольких компонентов верхнего уровня.
Допустим, ваше приложение имеет следующие уровни снизу вверх: NET, TCP, HTTP, REST, DATA MODEL, BUSINESS.
Если ваш бизнес-уровень хочет выполнить вызов покоя ... подождите секунду. Почему я это сказал? Почему я не произнес HTTP-запрос, TCP-транзакцию или отправил сетевые пакеты? Потому что они не имеют отношения к моему бизнесу. Я не собираюсь обращаться с ними, я не собираюсь смотреть на их детали. Я совершенно в порядке, если они глубоко в исключения, которые я получаю в качестве причины, и я не хочу знать, что они даже существуют.
Более того, это плохо, если я знаю детали, потому что если завтра я хочу изменить подчеркивающие транспортные протоколы, относящиеся к деталям, которые являются специфическими для протокола TCP, это означает, что моя абстракция REST не сделала хорошую работу, чтобы абстрагироваться от конкретная реализация.
При перемещении исключения из уровня в слой важно пересмотреть каждый его аспект и какой смысл это будет иметь для абстракции, которую обеспечивает текущий уровень. Это может быть замена исключения другим, это может объединить несколько исключений. Это может также перевести их из проверенного состояния в непроверенное или наоборот.
Конечно, фактические места, которые вы упомянули, имеют смысл - это отдельная история, но в целом - да, это может быть полезно.
источник
По моему мнению,
На уровне фреймворка мы должны отлавливать исключения во время выполнения, чтобы уменьшить количество блоков try catch для вызывающего в том же месте.
На уровне приложений мы редко фиксируем исключения во время выполнения, и я думаю, что эта практика была плохой.
источник