Когда использовать пользовательские исключения в сравнении с существующими исключениями против общих исключений

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

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

Приложение, использующее эту библиотеку, должно будет обрабатывать эти исключения так или иначе. Возможно, они могут решить просто сказать "Ошибка", или они могут захотеть предоставить пользователю более полезную информацию. Какая лучшая практика в этой ситуации? Создать настраиваемое исключение для каждой возможности? Использовать существующие исключения? Используйте Исключение и пропустите причину (throw new Exception("Badge is deactivated.");)? Я думаю, что это что-то вроде сочетания первых двух, используя существующие исключения, где это применимо, и создавать новые, где это необходимо (и группировать исключения, когда это имеет смысл).

Ответ 1

У вас есть два вида исключений.

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

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

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

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

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

Ответ 2

Я по существу согласен с вашим текущим мышлением.

  • При необходимости используйте существующие исключения ядра: ArgumentException, InvalidOperationException и т.д. Не пытайтесь пересобирать исключения, относящиеся к некоторому другому модулю. Используйте те исключения, которые имеют четкую, общую цель и не используют их для бизнес-правил. Например, InvalidOperationException должен указывать на плохую операцию с вашим API, а не на нарушение бизнес-правила.
  • Для исключений, специфичных для вашей библиотеки, создайте базовый класс исключений BadgeAuthException и всегда бросайте это. Конкретные сценарии должны каждый получить свой собственный подкласс (BadgeDeactivatedException, NoPermissionsAtWorkstationException и т.д.). Таким образом, приложения могут обрабатывать отдельные подсекции отдельно, если они этого хотят, но они также могут просто уловить общий BadgeAuthException, если они не хотят ограничиваться спецификой.
  • Независимо от того, что вы делаете, убедитесь, что поле Message всегда содержит полезную информацию, кроме только имени исключения.

Ответ 3

Использовать исключение и передать причину (throw new Exception ( "Значок деактивирован." );)

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

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

Ответ 4

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

Ответ 5

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