иерархия исключений и перечисление ошибок - PullRequest
8 голосов
/ 13 января 2009

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

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

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

Я снова работал с исключениями, и у меня был задумчивый момент, когда я подверг сомнению свои привычки исключений. Мне интересно, что все остальные делают и почему?

Иерархия или одно исключение с элементами данных.

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

Ответы [ 8 ]

12 голосов
/ 13 января 2009

Простое правило:

  • Если вы в конечном итоге выбрасываете исключения после их изучения, то вам нужна более тонкая иерархия исключений (за исключением редкого случая, когда проверка сопряжена со значительной логикой).
  • Если у вас есть классы исключений, которые никогда не перехватываются (только их супертипы), то вам нужна менее детализированная иерархия исключений.
11 голосов
/ 13 января 2009

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

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

Чтобы ответить на ваш вопрос, я использую иерархию исключений. Это намного шире, чем глубоко.

7 голосов
/ 13 января 2009

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

  • Создавайте новые классы исключений только тогда, когда вам нужно исключение, которое требует другого поведения .
  • Вместо этого добавляйте содержимое (перечисления, коды ошибок и т. Д.) В классы исключений, когда вы просто хотите, чтобы дополнительная информация была включена в исключение
  • Не создавайте новые классы, если они действительно вам не нужны. и помни, ЯГНИ ...
4 голосов
/ 13 января 2009

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

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

3 голосов
/ 13 января 2009

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

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

Я бы не использовал решение enum, но несколько типов исключений имеют достаточно широкий спектр, чтобы быть полезным. Как и DatabaseException вместо нескольких исключений, таких как TableNotFoundException, ColumnNotFoundexception и т. Д. По моему опыту, это лучше всего подходит для большинства разработчиков. Вы всегда можете добавить поле с кодом ошибки, который отображается для пользователя, чтобы упростить общение между пользователем и поддержкой.

2 голосов
/ 13 января 2009

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

Пример: Допустим, у вас есть типы исключений Ex1..Ex99, например, с. E14..E18 - дочерние элементы E1 и т. Д. Теперь вы решили заменить их одним исключением Ex и подтипами ST1..ST99. Что ты решил? Ничего - людям все еще приходится иметь дело со всеми возможностями. Что ты сделал хуже? Вы не можете игнорировать ST14-ST18 и рассматривать их как происхождение ST1. Теперь вы должны иметь дело со всеми 99 возможностями, поскольку у перечисляемых подтипов нет естественной, гибкой иерархии.

1 голос
/ 13 января 2009

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

Если что-то идет не так и может быть исправлено локально, то вам, вероятно, следует использовать коды ошибок и обрабатывать их тут же.

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

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

0 голосов
/ 13 января 2009

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

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

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