Какова цель обертывания исключения более низкого уровня в Java, если я просто собираюсь выбросить свое исключение обертки? - PullRequest
3 голосов
/ 06 июля 2011

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

  1. Просто собираюсь позволить исключениям всплыть наверх.
  2. Никогда не собираюсь делать что-то "уникальное", за исключением исключенного.

Например, у меня есть DAO, который выбрасывает исключение SQLException, а следующий уровень - это менеджер, который вызывает DAO. Общепринятая парадигма заключается в том, что я создаю исключение менеджера, оборачиваю свое исключение SQLException и затем выбрасываю исключение менеджера. Зачем? Если другой класс в цепочке все равно будет иметь дело с этим, то зачем его оборачивать?

Ответы [ 8 ]

10 голосов
/ 06 июля 2011

В вашем примере это может быть бесполезно. Но предположим, что вы пишете интерфейс со многими возможными реализациями. Предположим, например, что через два года вы переключаетесь с базы данных SQL на базу данных NoSQL. Ваш DAO будет вынужден объявить NoSQLException, и весь вызывающий код должен быть переписан. Принимая во внимание, что если SQLException или NoSQLException заключены в ваше пользовательское исключение, вызывающий код может остаться без изменений.

4 голосов
/ 06 июля 2011

В вашем конкретном примере, если у вас есть сервисный уровень, который вызывает DAO, вы не хотите, чтобы клиенты видели исключения SQL, такие как "ORA-00118: уникальное ограничение (BLABLA) нарушено".

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

3 голосов
/ 06 июля 2011

Ловить и перебрасывать ничего не получается. Лучше позволить этому пузыриться в этом случае.

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

3 голосов
/ 06 июля 2011

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

Один из примеров обертывания исключений, который может быть полезен, - это "преобразование" исключений, специфичных для реализации, во что-то более специфичное длярамки в сценарии IoC / DI.Например, если у вас есть фреймворк, который выполняет некоторую работу, вы хотите оградить клиентский код от необходимости «знать» кучу конкретных исключений.Таким образом, вы создаете набор общих исключений, которые выдают ваши плагины и которые ваш клиентский код знает и может обработать.Как исключения доступа к данным для множества различных бэк-эндов.

1 голос
/ 06 июля 2011

Java заставляет вас явно объявить, какие исключения могут быть выброшены. исключения обертывания предотвращают:
1. представьте, какова ваша конкретная реализация (более высокий уровень может не знать, что вы используете sql в качестве базы данных, поэтому вы можете просто выбросить MyAppException).
2. в противном случае список объявленных исключений увеличится со временем, что приведет к тому, что более высокий уровень будет заботиться обо всех них, что может быть не очень аккуратно.

0 голосов
/ 07 июля 2011

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

OperationFailedStateOkException
Операция не может быть завершена, но состояние локальной и глобальной системы в порядке, за исключением той степени, которая подразумевается этим отказом (например, попытка сослаться на несуществующий элемент в Словаре).
OperationFailedLocalStateCorruptException
Операция не может быть завершена, и состояние локальной системы повреждено (например, при попытке обратиться к элементу из поврежденного словаря).
OperationFailedGlobalStateCorruptException
Операция не может быть завершена, и состояние глобальной системы повреждено (например, поврежден общий кэш).

Обратите внимание, что во многих случаях вызывающая подпрограмма будет интересоваться не так сильно, как причиной сбоя, так и тем, что подразумевает сбой в состоянии системы. Исключения первого типа, как правило, можно безопасно перехватить и возобновить выполнение, если программист знает, почему они могут произойти и что с ними делать. В некоторых случаях их может потребоваться повторно использовать как исключения второго типа (например, если система не смогла выполнить какую-либо операцию, которая была бы необходима для поддержания согласованности в структуре данных). Те, которые второго типа, должны быть перехвачены и переброшены как первый тип только на уровне, на котором будет отменено поврежденное состояние (например, подпрограмма «Загрузить документ» может перехватывать такие исключения и перебрасывать как исключение «состояние в порядке», если есть). поврежденные структуры данных, использованные при неудачной попытке загрузить документ, будут отброшены). Те, которые третьего типа, как правило, должны вызывать закрытие программы.

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

0 голосов
/ 06 июля 2011

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

0 голосов
/ 06 июля 2011

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

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

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