Я держу это простым.
Библиотека имеет базовый тип исключений, расширенный от std ::: runtime_error (это из C ++, применимо в зависимости от других языков). Это исключение принимает строку сообщения, чтобы мы могли войти; каждая точка выброса имеет уникальное сообщение (обычно с уникальным идентификатором).
Вот и все.
Примечание 1 : В ситуациях, когда кто-то, поймавший исключение, может исправить исключения и перезапустить действие. Я добавлю производные исключения для вещей, которые потенциально могут быть однозначно исправлены в удаленном месте. Но это очень и очень редко (помните, что зрелище вряд ли будет близко к точке броска, поэтому решить проблему будет сложно (но все зависит от ситуации)).
Примечание 2 : Иногда библиотека настолько проста, что не стоит давать ей свое собственное исключение, что делает std :: runtime_error. Важно иметь исключение, только если способность отличить его от std :: runtime_error может дать пользователю достаточно информации, чтобы что-то с ним сделать.
Примечание 3 : В классе я обычно предпочитаю коды ошибок (но они никогда не будут выходить через общедоступный API моего класса).
Глядя на ваши компромиссы:
Компромиссы, которые я вижу, включают:
Дополнительные классы исключений могут позволить очень тонкие уровни обработки ошибок для пользователей API (склонны к пользовательской конфигурации или ошибкам данных, или файлам не найдено)
Действительно ли больше исключений дают вам более точный контроль зерна? Возникает вопрос: может ли код перехвата исправить ошибку, основанную на исключении? Я уверен, что есть такие ситуации, и в этих случаях у вас должно быть другое исключение. Но из всех исключений, которые вы перечислили выше, единственное полезное исправление - это генерация большого предупреждения и остановка приложения.
Дополнительные классы исключений позволяют включать информацию об ошибке в исключение, а не просто строковое сообщение или код ошибки
Это отличная причина для использования исключений. Но информация должна быть полезна человеку, который ее кеширует. Могут ли они использовать информацию для выполнения некоторых корректирующих действий? Если объект является внутренним для вашей библиотеки и не может использоваться для влияния на какой-либо API, тогда эта информация бесполезна. Вы должны быть очень конкретными, чтобы выброшенная информация имела полезную ценность для человека, который может ее поймать. Человек, который его ловит, обычно находится за пределами вашего общедоступного API, поэтому настройте вашу информацию так, чтобы ее можно было использовать с вещами в вашем публичном API.
Если все, что они могут сделать, это зарегистрировать исключение, то лучше просто выдать сообщение об ошибке, а не много данных. Поскольку ловец обычно строит сообщение об ошибке с данными. Если вы создадите сообщение об ошибке, оно будет одинаковым для всех перехватчиков, если вы позволите перехватчику создать сообщение об ошибке, вы можете получить одно и то же сообщение об ошибке по-разному в зависимости от того, кто звонит и перехватывает.
Меньше исключений, но встраивание кода ошибки, который можно использовать как поиск
Вы должны определить погоду, код ошибки может быть использован осмысленно. Если это возможно, у вас должно быть собственное исключение. В противном случае ваши пользователи теперь должны реализовать операторы switch внутри там catch (что сводит на нет весь смысл того, что catch автоматически обрабатывает вещи).
Если это невозможно, то почему бы не использовать сообщение об ошибке в исключении (нет необходимости разделять код и сообщение, это вызывает боль при поиске).
Возвращение кодов ошибок и флагов непосредственно из функций (иногда невозможно из потоков)
Возвращение кодов ошибок прекрасно внутри. Это позволяет вам исправлять ошибки тут же, и вы должны убедиться, что исправили все коды ошибок и учли их. Но утечка их через ваш публичный API - плохая идея. Проблема в том, что программисты часто забывают проверять состояния ошибок (по крайней мере, за исключением непроверенной ошибки, приложение будет вынуждено выходить из необработанной ошибки, как правило, повреждает все ваши данные).
Реализована система события или обратного вызова при ошибке (предотвращает раскручивание стека)
Этот метод часто используется в сочетании с другим механизмом обработки ошибок (не как альтернатива). Подумайте о своей программе Windows. Пользователь инициирует действие, выбирая пункт меню. Это создает действие в очереди событий. Очередь событий в конечном итоге назначает поток для обработки действия. Предполагается, что поток обрабатывает действие и в конечном итоге возвращается в пул потоков и ожидает другую задачу. Здесь исключение должно быть поймано в основе потоком, которому поручено задание. Результат отлова исключения обычно приводит к тому, что для основного цикла генерируется событие, которое в конечном итоге приводит к отображению пользователю сообщения об ошибке.
Но если вы не сможете продолжить работу в условиях исключения, стек будет разматываться (по крайней мере, для потока).