Есть ли хорошие ресурсы для планирования использования исключений с точки зрения архитектуры? (Или предоставьте свои предложения прямо здесь.) В проектах, над которыми я работал, я обнаружил, что несколько общих исключений используются снова и снова и имеют тенденцию терять свое значение. Из: http://jamesjava.blogspot.com/2007/10/exception-plan.html
Как следует планировать исключения на архитектурном уровне?
Ответы (4)
Я наполовину согласен с комментарием Апокалиспа. Экземпляры исключения должны быть зарезервированы для случаев, когда произошла ошибка данных или обработки, но она может быть устранена вмешательством пользователя или системы. Экземпляры RuntimeException должны быть зарезервированы для тех случаев, когда никакое вмешательство в пределах вашего приложения не может решить проблему. Таким образом, эти два типа известны как Checked и Unchecked исключения.
Примером исключений Unchecked может быть, если физический ресурс (такой как база данных или шина сообщений) недоступен. В этом случае RuntimeException хорош, потому что вы не планируете, что ресурс будет недоступен, поэтому вашей бизнес-логике не нужно постоянно проверять наличие DatabaseUnavailableException или что-то подобное. Вы можете обрабатывать RuntimeExceptions по-другому (возможно, AOP отправляет электронное письмо), чтобы сообщить о сбое и позволить персоналу или службе поддержки устранить физическую проблему.
Примерами проверенных исключений могут быть неправильный ввод данных, неполный доступ к данным или что-то, что на самом деле нарушает бизнес-логику, но может быть проверено и восстановлено. Примером этого может быть то, что пользователь, которого вы искали, недоступен. Это отдельное условие в вашей бизнес-логике, которое может быть проверено и обработано (скажем, частью просмотра вашего приложения, которая затем сообщает пользователю сообщение об исключении как сообщение об ошибке).
Многие фреймворки используют эту модель, и кажется, что она работает лучше, чем я видел в противном случае.
При этом многие заменяют проверенные исключения возвращаемыми значениями NULL, -1, пустой строкой или Number.MIN_VALUE. Хотя это нормально, если вы обычно не ожидаете этих значений от источника данных или метода, вероятно, их следует представлять как исключение.
Обычно я считаю, что зацикливаться на проверенных исключениях — это излишество. Исключения должны быть зарезервированы для непредвиденных ошибок, после которых программа не может разумно восстановиться. Для них я склонен согласиться с тем, что вы заметили, что специальные типы ошибок имеют тенденцию терять свое значение.
Как правило, генерируется исключение, когда выполняются все следующие условия:
- Состояние не может быть восстановлено отсюда.
- Нельзя разумно ожидать, что вызывающий абонент оправится от этого состояния.
- Кто-то захочет отладить ситуацию, поэтому он может захотеть увидеть трассировку стека.
Вы обнаружите, что если все это верно, то тип исключения не важен, и вы также можете выдать java.lang.Error. Если какое-либо из них ложно, то исключение, вероятно, является излишним (вам действительно нужны тип, сообщение и трассировка стека?)
Вместо этого рассмотрите возможность увеличения возвращаемого типа методов, чтобы указать ожидаемые виды сбоев. Например, используйте Вариант‹A› type для методов, в которых в некоторых случаях имеет смысл не возвращать значения. Используйте A, B›. type для методов, в которых может потребоваться вернуть значение, тип которого зависит от неудачи или успеха. Там, где раньше у вас могли быть специализированные подтипы исключений, вы можете вместо этого просто использовать «Либо‹Fail,A›», где Fail — это просто перечисление типов ожидаемых сбоев.
Я стараюсь, чтобы количество мест, где используется try/finally, значительно превышало количество мест, где используется try/catch. catch обычно зарезервирован для перехвата исключений на верхнем уровне, где их можно разумно обработать, или для обработки исключений из API платформы.
В этом случае, пока вы даете исключениям осмысленные сообщения и при необходимости создаете цепочки исключений, невозможность идентифицировать исключение по его классу не является большой потерей. Я часто выбрасываю RuntimeException, а не пытаюсь разработать класс исключений для каждого мыслимого случая ошибки, но ваше мнение по этому поводу будет зависеть от того, где вы сидите в дебатах о проверенных и непроверенных исключениях.