Мысли по поводу генерации и обработки исключений
На основании своего личного опыта, выработал некую концепцию работы с исключениями. Данная концепция «заточена» для приложений, основанных на бизнес-процессах. Для системных и прочих программ она может оказаться малоэффективной. Т.к. я преимущественно использую .Net, то примеры иключений приведены для .Net-платформы.
Концепция представлена в виде таблицы:
Причина генерации исключения | Детали | Класс исключения (.Net платформа) | Как обработать исключение |
---|---|---|---|
1. Нарушение правил бизнес-процесса | Нарушения любого внутреннего правила вашей системы. К примеру, попытка снять средства со счета с нулевым балансом. Причем правила могут быть гибкими: для некоторых типов счетов можно разрешить уходить в минус. |
Необходимо реализовать свой класс, наследник Exception (ранее рекомендовали наследоваться от ApplicationException, теперь изменили). Обычно исключение содержит полезную для пользователя информацию. |
Обработайте в соответствии с внутренними правилами вашей системы. Чаще всего прекратить обработку текущей операции и выдать сообщение пользователю. Записывать в лог-файл такие типы исключений не нужно. |
2. Некорректные данные | 2.1. Некорректные данные, вводимые пользователем. К примеру, вместо цифры введена буква. | По возможности, обработать без генерации исключения (простой проверкой или использовать TryParse). Иначе, аналогично 2.2. | Подсказать пользователю, какие данные являются не корректными. Предоставить возможность исправить их. Записывать в лог-файл не нужно. |
2.2. Некорректные данные от источника данных (Web-сервис, файл, реестр, база данных). К примеру, вместо XML-формата получен обычный текст. | Четких правил нет. FormatException, InvalidDataException и др. Обычно в .Net вводят специальный класс исключения, который возникает при некорректности данных. Примеры: ConfigurationException, XmlException, SqlException, SqlTypeException, WebException. Однако возникновение этих исключений вовсе обязательно означает, что проблема именно в некорректности данных (есть другие причины). Но вполне могут применить и ArgumentException, InvalidOperationException и пр. Это значительно усложняет обработку исключения. |
Два варианта: либо поставщик данных нарушает протокол, либо подписчик не полностью реализовал обработку данных по протоколу. Если поставщик данных не адекватен – можно подставить «костыль». Если ваш «костыль» смог решить проблему – записывать в лог файл не нужно. Иначе записать детали в лог файл и решать проблему на одном из 2-х уровней. |
|
3. Некорректный код | 3.1. Нарушение контракта. | IndexOutOfRangeException, NullReferenceException, AccessViolationException, ArgumentException, ArgumentNullException, ArgumentOutOfRangeException, InvalidCastException и др. | Записать детали исключения в лог-файл, отправить лог разработчику. Такие исключения являются 100% виной разработчика. Предупредить пользователя об ошибке. В зависимости от того где возникла ошибка, решить закрывать ли программу (если могут быть повреждены данные). Исправить ошибку в коде на основании данных лога и обновить версию программы. |
3.2. Нарушение инварианта. | InvalidOperationException | ||
4. Ошибка системы (часто связь с аппаратной проблемой). | Не устранимые:* ExecutionEngineException, StackOverflowException, OutOfMemoryException. В 99% случаев эти исключения обработать не представляется возможным. | В 99% случаев – никак не обрабатывать. Можно попытаться записать данные исключения в лог. |
Замечу, что данная структуризация основана на базовых понятиях:
1. Аппаратное обеспечение.
2. Программное обеспечение. В свою очередь проблемы программного обеспечения разделяются на 2 подкласса: проблема данных и проблема кода.
Так что, в принципе, ничего новго я не придумал.
Стоит заметить, что ошибки одной категории могут пораждать исключения другой категории. К примеру, некорректный код может вызвать StackOverflowException. Хотя, некорректные данные в идеале не должны вызывать ошибки некорректного кода или системные ошибки.
Хотелось бы услышать мысли по теме.