Я работаю в качестве подрядчика, разрабатывающего корпоративное Java-приложение для моего клиента в роли технического лидера. Приложение будет использоваться конечными пользователями, и будет команда поддержки, которая будет поддерживать приложение, когда мы уйдем.
У других технических руководителей, с которыми я работаю, сложилось впечатление, что обработка исключений сделает код грязным. Система должна выдавать проверенные исключения только из уровня Service, а остальная часть кода должна выбрасывать исключения во время выполнения из всех других уровней, так что нет необходимости обрабатывать непроверенные исключения.
Зачем когда-либо генерировать непроверенное исключение в бизнес-приложении?
Из моего прошлого опыта об исключениях во время выполнения:
1) Непроверенные исключения делают код непредсказуемым, потому что они не отображаются даже в Javadoc.
2) Бросать непроверенные исключения в бизнес-приложении не имеет смысла, потому что, когда вы бросаете его, и оно идет прямо в лицо пользователям, как вы объясните это пользователю? Я видел достаточно веб-приложений, которые показывают, 500 -Internal Error. Contact Administrator
что ничего не значит для конечного пользователя или для группы поддержки, управляющей приложением.
3) Создание исключений времени выполнения вынуждает пользователей класса, генерирующих исключение, проходить через исходный код для отладки и видеть, почему выбрасывается исключение. Этого можно избежать только в том случае, если Javadoc исключительной ситуации времени выполнения отлично документирован, что, как я считаю, никогда не бывает.
источник
@throws
тега, что, кстати, является хорошей практикой.@throws
тег Javadoc для документирования каждого непроверенного исключения, которое может вызвать метод, но не используйте ключевое слово throws, чтобы включить непроверенные исключения в объявление метода.Ответы:
Проверенные исключения являются неудачным объяснением в дизайне языка. Они вынуждают вас иметь чрезвычайно дырявые абстракции и грязный код. Их следует избегать как можно больше.
Что касается ваших очков:
1) Проверенные исключения делают код грязным и не менее непредсказуемым, потому что они появляются везде .
2) Как проверенное исключение показывается пользователю лучше? Единственная реальная разница между проверенными и непроверенными исключениями является технической и затрагивает только исходный код.
3) Когда-нибудь слышали о следах стека? Они точно сообщают вам, где было сгенерировано исключение, независимо от того, установлено оно или нет. На самом деле, проверенные исключения, как правило, хуже для отладки, потому что они часто переносятся, что приводит к более длинным и уродливым трассировкам стека, или даже вообще теряются, потому что перенос был сделан неправильно.
Существует два вида исключений: те, которые возникают «нормально» и обычно обрабатываются очень близко к месту их возникновения, и те, которые действительно исключительны и могут обрабатываться в общем случае на очень высоком уровне (просто прервите текущее действие и зарегистрируйте его / покажи ошибку).
Проверенные исключения были попыткой поместить это различие в синтаксис языка в точке, где определены исключения. Проблемы с этим
источник
SQLException extends Exception
означает, что выбор выбрасывать,SQLException
потому что ошибка связана с доступом к БД, автоматически означает, что исключение проверено. И вы можете отлично документировать непроверенные исключения в комментариях Javadoc. Хорошо работает для всех других языков.Я считаю, что тип создаваемого исключения зависит от того, что делает ваш код.
Я выбрасываю проверенные исключения, когда ожидаю, что они могут происходить довольно часто (например, пользователи, вводящие сомнительные данные), и ожидаю, что вызывающий код справится с ситуацией.
Я выбрасываю непроверенные / исключительные ситуации времени выполнения (не так часто, как проверено), когда у меня есть редкая ситуация, которую я не ожидаю обработки вызывающим кодом. Примером может служить какая-то странная ошибка, связанная с памятью, которую я никогда не ожидал. Не проверены те виды ошибок, которые вы ожидаете, чтобы закрыть приложение.
Никакие исключения не должны появляться перед пользователем без некоторого уровня поддержки. Даже если это просто «пожалуйста, скопируйте и вставьте этот дамп ошибки в электронное письмо». Нет ничего более раздражающего для пользователя, чем сообщение о том, что есть ошибка, но, если ей не дают подробностей или действий, они могут предпринять, чтобы исправить ее.
Я предполагаю, что философия, которую вы упоминаете, исходит из одного из двух источников:
источник
Если вы не хотите непроверенных исключений времени выполнения, то почему вы используете Java? Существует возможность исключений во время выполнения почти везде - в частности, исключения NullPointerException, ArithmeticException, ArrayIndexOutOfBounds и т. Д.
И когда вы однажды прочитаете файлы журналов какой-либо системы J2EE, например, установки SAP NetWeaver, вы увидите, что такие исключения случаются буквально все время.
источник
Есть несколько правил обработки исключений, которые вы должны иметь в виду. Но сначала вы должны помнить, что исключения являются частью интерфейса, предоставляемого кодом; документировать их . Это особенно важно, когда интерфейс общедоступен, конечно, но это очень хорошая идея и для частных интерфейсов.
Исключения следует обрабатывать только в том месте, где код может сделать что-то разумное с ними. Худший вариант обработки - ничего с ними не делать, что следует делать только тогда, когда это абсолютно правильный вариант. (Когда в моем коде возникает такая ситуация, я добавляю комментарий на этот счет, чтобы не беспокоиться о пустом теле.)
Второй худший вариант - выбросить несвязанное исключение без указания причины. Проблема здесь в том, что информация в исходном исключении, которая позволила бы диагностировать проблему, потеряна; вы создаете что-то, с чем никто ничего не может сделать (кроме как жаловаться, что «это не работает», и мы все знаем, как мы ненавидим эти сообщения об ошибках).
Гораздо лучше регистрировать исключения. Это позволяет кому-то выяснить, в чем заключается проблема, и устранить ее, но вы должны регистрировать исключение только в том месте, где в противном случае оно будет потеряно или передано по внешнему соединению. Это не потому, что ведение журнала чаще всего является серьезной проблемой, а скорее потому, что чрезмерное ведение журнала означает, что вы просто получаете журнал, занимающий больше места без дополнительной информации. После того, как вы вошли исключение, вы можете сообщить PRECIS к пользователю / клиента с чистой совестью ( до тех пор , как вы можете также включать в себя время генерации - или другой идентификатор корреляции - в этом докладе , так что короткая версия может быть подобран с детализацией при необходимости).
Конечно, наилучший вариант - полностью обработать исключение, полностью устраняющее ситуацию с ошибками. Если вы можете сделать это, во что бы то ни стало сделайте это! Это может даже означать, что вы можете избежать регистрации исключения.
Одним из способов обработки исключения является создание другого исключения, которое предоставляет описание проблемы более высокого уровня (например, «
failed to initialize
» вместо «index out of bounds
»). Это хороший шаблон, если вы не потеряете информацию о причине исключения; используйте подробное исключение, чтобы инициализировать исключениеcause
более высокого уровня или зарегистрируйте подробности (как обсуждалось выше). Ведение журнала наиболее уместно, когда вы собираетесь пересечь межпроцессную границу, такую как вызов IPC, потому что нет никакой гарантии, что низкоуровневый класс исключений будет вообще присутствовать на другом конце соединения. Хранение в качестве прикрепленной причины наиболее целесообразно при пересечении внутренней границы.Другой шаблон, который вы видите, это «поймай и отпусти»:
Это анти-шаблон, если у вас нет ограничений типа из других
catch
предложений, которые означают, что вы не можете просто позволить исключению пройти самостоятельно. Тогда это просто уродливая особенность Java.Нет реальной разницы между проверенными исключениями и непроверенными, за исключением того факта, что вы должны объявлять проверенные исключения, которые пересекают границы метода. Хорошей идеей будет документировать неконтролируемые исключения (с
@throws
комментариями javadoc), если вы знаете, что они намеренно генерируются вашим кодом. Не преднамеренно выбрасывайтеjava.lang.Error
или его подклассы (если вы не пишете реализацию JVM).Мнение: случай непредвиденной ошибки всегда представляет ошибку в вашем коде. Проверенные исключения являются способом управления этой угрозой, и когда разработчики намеренно используют непроверенные исключения как способ избежать проблем с обработкой ошибок, вы накапливаете большой технический долг, который вам придется некоторое время устранять. если вы хотите надежный код. Небрежная обработка ошибок непрофессиональна (и рассмотрение обработки ошибок - хороший способ определить, насколько хорош программист на самом деле).
источник
Я думаю, что вы должны только бросить проверенное исключение, когда приложение может восстановиться. Таким образом, пользователи вашей библиотеки должны перехватывать эти исключения и делать то, что нужно для восстановления. Все остальное должно быть не проверено.
Как пример,
Если ваше приложение загружает данные из файла или базы данных. Потом,..
вызывающая сторона всегда может перехватить проверенное исключение MissingDataFileException, а затем попытаться загрузить данные из базы данных.
источник