Как управлять исключениями в API? - PullRequest
1 голос
/ 04 сентября 2011

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

Что вы делаете с исключениями? Есть разные возможности:

  • Всегда выбрасывайте их клиенту . Исключения являются накопительными, поэтому, если метод A использует закрытый метод B, а метод B выдает исключение, а метод A выдает другое исключение, клиент видит 2 исключения и должен видеть только последнее, потому что это метод, который он вызывает. Мы можем накопить много исключений.

  • Выдает только исключения, созданные в методе, который вызывает клиент. Что мы делаем с внутренними исключениями? Просто напечатать исключение (printStackTrace())? Преобразовать эти проверенные исключения в непроверенные исключения, чтобы их нужно было только выбросить?

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

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

Ответы [ 3 ]

2 голосов
/ 04 сентября 2011

Что касается вашего первого замечания - всегда лучше создать специфичную для домена иерархию исключений для вашего API (например, DataAccessExceptions * в Spring) и обернуть все, что выходит вашим клиентам.

Практическое правило относительно проверенных / непроверенных исключений:

  • Бросок не проверено исключения, когда клиент ничего не может сделать с ошибкой
  • Бросок проверено исключения, когда клиент должен обработать ошибку

Относительно второго пункта - никогда не скрывайте внутренние ошибки, если они каким-либо образом влияют на клиента.Кроме того, не выводите информацию об ошибке в побочный канал (например, e.printStackTrace()), о котором клиент может не знать.Если вам необходимо предоставить неисключительную информацию своим пользователям, у вас есть два варианта:

  1. Предоставить методы, которые принимают Logger некоторого вида
    • Плюсы: явный, без дополнительныхЗависимости
    • Минусы: загромождает API, громоздкий в использовании
  2. Используйте SLF4J фасад для ведения журнала и ведите запись в обычном режиме
    • Плюсы: поддерживает API в чистоте
    • Минусы: зависимость от slf4j-api
1 голос
/ 04 сентября 2011

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

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

Проверенные исключения, как правило, лучше всего использовать, расширяя Exception. Они, как правило, легче отлаживать. Но, конечно, вы можете захотеть использовать непроверенные исключения в некоторых случаях.

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

Куда бы вы ни выдавали исключение, убедитесь, что вы добавили в него осмысленное сообщение, понятное клиенту.

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

0 голосов
/ 04 сентября 2011

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

class A {
  void methodA() throws AException { /*...*/ }
}

class B {
  void methodB() throws BException {
    try {
      new A().methodA();
    } catch(AException e) {
      throw new BException("A problem occured in methodA", e);
    }
  }
}

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

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