Как стать автором
Обновить

Использование Exception (обновлённая версия).

Время на прочтение4 мин
Количество просмотров9.2K

throw new Exception or not throw new Exception, вот в чём вопрос!



Доброе время суток!

Когда же использовать технологию исключений? Когда лучше воздержаться и стоит ли воздерживаться?


Какое-то время назад, я пытался описать практику применения подхода Exception`ов, когда стоит и когда не стоит применять данную технологию. Получилось у меня, мягко говоря, не очень. Зато я получил порцию «здоровой» критики :). За что огромное спасибо: smira habralan tagirovarthur Thecentury. Так что, кому не жалко, могут поделиться с ними плюсиками ;).

Переходим к делу

Когда-то я задался вопросов: «Когда стоит использовать технологию Exception?» (Упор сделан на C#). Временами возникают у меня такие ситуации, что задумываешься, а стоит ли применять или не стоит… Поковырявшисть в интернете, я узнал, что есть 2 лагеря(как полагается) — сторонники и противники использования Exception. Лагерь противников, возглавил Joel Spolsky.
Здесь я приведу список тех аргументов, которые использует Джоэл:
1. Они «не видны» в исходном коде. Поясню более детально. Предположим вы вызываете некий метод некого класса:
someClass.SomeMethod();
Вы не можете с уверенностью сказать, будет ли сгенерировано исключение. Не нужно кидаться в меня тапками, в Visual Studio при наведении курсора мыши на метод, можно увидеть подсказочку, какое исключение может быть сгенерировано (при условии, что разработчики сделали это описание в документации). Не знаю как в других IDE, но в VS такая возможность есть. Конечно это несомненный минус для тех кто исповедует «истинную веру», тобишь Notepad(или аналоги) и компилятор.

2. Создаются «непредвиденные» точки выхода из метода. Предположим у вас есть примерно такой код:
someClass.PossibleException();
otherClass.DoOtherThing();
так вот, нет гарантии что метод DoOtherThing() будет выполнен, если метод PossibleException() «киданёт» исключение.

3. Exception`ы более медленный механизм, чем «код возврата ошибки». Joel почему-то об этом ничего не упоминал, поэтому этот аргумент добавлен мной. Почему это более медленный вариант разберём ниже.

Как видно 3 аргумента(2 от Джоэла и 1 от меня :)). Притом довольно обоснованные. Скорость сферического коня в вакууме здесь совершенно не причём

А теперь давайте рассмотрим аргументы в защиту данного подхода:
1. Это ООП подход, придуманный и созданный в рамках данной концепции. Я думаю расписывать преимущества ООП подхода, над «классическим» не нужно, все прекрасно осведомлены.

2. Удобство использования. Рассмотрим классический пример, есть у вас метод классa SomeMethod(), который возвращает целое число — код возврата ошибки, вы наследуетесь от класса содержащего этот метод и перегружаете его, с целью расширения функционала. Таким образом, метод мог вернуть, предположим, значения {1,2,3,4}; после расширения {1,2,3,4,5,...,10}. Это вызовет увеличение кода, который должен обработать результать работы метода. Так например, вы используете ArgumentException; можно добавить генерацию этого исключения, изменив его содержание. Т.е. тем самым можно сократить неразбериху, создаваемую большим количеством возвращаемых кодов.

3. Высокая степень инфомативности. В вызываемом методе произошла ошибка, вы можете получить код ошибки и потом копаться в документации или исходниках, выискивая причины этой ошибки. Или же можно получить содержимое стека(узнать, а где конкретно произошла ошибка), получить какое-то текстовое понятное сообщение(при условии, что разработчики не написали throw new Exception("");), да и ещё много всяких полезностей, которые очень сильно способны облегчить жизнь разработчику (для более детальной информации, стоит обратиться к документации).

4. Принцип использования. Впринципе это перекликается с первым пунктом, но я предпочёл вынести отдельно. Предположим какой-то метод в глубине стека сгенерировал исключение. А вызывающий его метод не знает что делать, тогда исключение передаётся на уровень выше. В конечном итоге, либо будет найден обработчик, который адекватно прореагирует на это исключение, либо… «сообщение пользователю». Я стараюсь в своей практике применять первый подход. В случае кода возврата ошибки, гнать ошибку «наверх» в поисках, «а кто же должен её обработать?» крайне не удобно, да и иногда не предосатвляется возможным, т.к. один метод может возвращать int, другой bool, в конечном итоге, мы так и не узнаем, что же произошло.

Как видно 3:4. Притом, с точки зрения разработчика использование исключений более удобно.

Теперь я бы хотел рассказать, почему же исключения более медленный механизм: создаётся объект исключение, а так же в стеке вызовов ищется обработчик который бы мог обработать это исключение. Что само собой «потребляет» время. В жизни нет ничего бесплатного, что-нибудь нужно потратить(деньги/время/нервы/etc).

Как видно из приведённого выше сравнения, исключения более удобны. Но не стоит ими злоупотреблять. Исключения именно потому и названы так, что возникать должны только в исключительных ситуациях! Если вы считали 2 байта из файла, притом нет принципиальной разницы — должны они быть в таком порядке или в обратном. Не стоит быстрее вбивать код создающий исключение. Можно просто у себя поменять их местами и продолжить работу дальше. Пример немножко надуманный, но я думаю понятный :).

Теперь, я думаю, стоит подвести итог:
Исключения использовать нужно, но с умом! Для себя я выделил одну ситуацию, когда я их использовать не буду — если ко мне поступают данные, изначально плохие и мне критична только скорость работы программы, ибо данные «выпрямить» по той или иной причине не получается, то я не буду использовать исключения. Во всех же остальных случаях, я предпочту использовать исключения. Думаю в своих измышлениях я не одинок.
Теги:
Хабы:
Всего голосов 35: ↑24 и ↓11+13
Комментарии50

Публикации