Определение исключений, которые могут быть выброшены из API инструментария - PullRequest
6 голосов
/ 04 декабря 2009

Существуют ли передовые или отраслевые стандарты для исключения из API инструментария?

Должны ли методы, ориентированные на пользователя, перехватывать и запаковывать Exception в каком-то виде CustomException, чтобы пользователям приходилось беспокоиться только о CustomException выходах из API?

Или это соглашение просто позволять этим пузыриться?

Мы заинтересованы в том, чтобы документировать все возможные исключения, которые могут вызывать наши методы API. (Например, если наш метод API вызывает Stream.Write(), который выдает 4 или 5 исключений, нам придется документировать все из них в дополнение к другим исключениям, которые могут вызывать другие вызываемые методы.)

Мы думали сделать что-то вроде этого:

public void customerFacingApiMethod(){
   try {
      //api functionality goes here
   } catch (Exception e) {
      throw new CustomException(e);
   }
}

Ответы [ 9 ]

13 голосов
/ 04 декабря 2009

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

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

3 голосов
/ 04 декабря 2009

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

  • Бросить исключение, полученное ArgumentException, если аргумент от клиента недопустим (используйте ArgumentNullException, ArgumentOutOfRangeException и т. Д. В зависимости от ситуации).
  • Выдает IOException -произведенное исключение для ошибок ввода-вывода.

Etc ...

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

3 голосов
/ 04 декабря 2009

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

1 голос
/ 04 декабря 2009

Проблема с перехватом System.Exception в общем случае заключается в том, что, делая это, вы фактически говорите: «Я понятия не имею, почему это не удалось, и это нормально, потому что я знаю, что могу продолжать в любом случае! «

Это редко, если вообще так, правда.

Объединение всех исключений в один пользовательский тип исключений означает, что ваши потребители просто поймают этот тип - что является моральным эквивалентом перехвата System.Exception. Выполняя это, вы можете удовлетворить некоторые правила политики / FXCop, но на самом деле вы просто перехватываете System.Exception.

Что касается политики исключений, я бы начал с вопроса: «Если бы я не знал, с чем на самом деле говорил этот API, к какому исключению я бы ожидал вернуться?» И помните, что метод - это запрос к объекту сделать что-то, а исключение - это способ объекта сообщить вам, что он не может, и почему .

1 голос
/ 04 декабря 2009

Существует два типа исключений (игнорирование StackOverflowException и т. Д., С которыми вы ничего не можете поделать):

  1. Те, которые вызваны внешними проблемами (такими как файловый IO), которые должны быть обработаны.
  2. Те, которых всегда можно избежать при правильно проверенном вводе.

Обычно имеет смысл передавать исключения типа IO в стек вызовов без изменений, поскольку в любом случае вы ничего не можете с этим поделать. Исключениями могут быть ожидаемые ошибки, для которых вы можете повторить попытку или попросить пользователя, что делать, если ваш API работает на уровне графического интерфейса пользователя (что было бы довольно необычно).

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

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

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

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

1 голос
/ 04 декабря 2009

То, что говорит Фредрик Морк, очень верно. Я также хотел бы добавить к этому, что вы можете легко документировать исключения, создаваемые с помощью комментариев xml (и GhostDoc).

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

Если у вас глубокий стек вызовов в вашем API и особенно если цикломатическая сложность становится высокой (то есть количество возможных ветвей), вы не можете восстановить все возможные исключения, которые могут быть выброшены (возможно, во время выполнения?)

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

1 голос
/ 04 декабря 2009

Не используйте одно и то же исключение для всех.

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

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

1 голос
/ 04 декабря 2009

Мне это не нравится. Если вы включите все исключения в CustomException, будет трудно отловить определенные исключения, не выполняя поиск внутри объекта для InnerExcpetion (возможно, на нескольких уровнях, если ваш API также использует другие API, которые делают то же самое). Если есть исключение OutOfMemoryException, я хотел бы знать об этом без необходимости искать его.

0 голосов
/ 07 декабря 2015

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

Для этого сначала определите абстрактный тип базового исключения:

CustomException

... и затем выводить из него более конкретные типы исключений. Например:

CustomFooException
CustomBarException
CustomFizException
CustomFuzException

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

Подробнее об идее разработки иерархии классов исключений см. этот ответ и другие ответы на этот вопрос: Зачем создавать пользовательские исключения в .NET?

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

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