Реальная выгода от того, что тип исключения E наследуется от типа F, очевидно, когда E перехватывается модулем, который точно не знает, что такое E, но знает о F. Предполагая, что наследование имеет смысл, модуль имеет разумный надежда предпринять правильные корректирующие действия для исключения E, основываясь на том, что это своего рода исключение E.
Так что я склонен классифицировать исключения в зависимости от того, как они могут быть разумно обработаны. Например, типичный бизнес-процесс может использовать что-то вроде:
- ConfigurationException - вещи, которые можно исправить, изменив файл конфигурации. Например. Конфигурация не может быть проанализирована или не соответствует. Надлежащий ответ - предупредить пользователя о необходимости исправить конфигурацию (если возможно, с полезными советами).
- InfrastructureException - вещи, которые могут время от времени работать неправильно с ресурсами, находящимися вне контроля программы, такими как удаленные серверы и т. Д. Соответствующим ответом часто является отключение, повторная попытка после паузы и отказ в случае слишком большого количества сбоев.
- DataException - вещи, которые неверны во входящих данных. Соответствующим ответом является регистрация жалобы (и, возможно, данных) и игнорирование этого сообщения.
Конечно, они могут быть разделены на подклассы. Но различия на этом уровне часто более полезны для модулей, которые ближе к источнику исключения. Если исключение всплывает на всем пути к основному модулю, то обычно есть только несколько возможных действий, и легче всего иметь взаимно-однозначное соответствие между этими действиями и операторами catch
, на которые они отвечают.