Когда нужны исключения
Предисловие
Тема Исключений (за и против) не нова, и уже не раз обсуждалась. Но всё же, я надеюсь, что каждый из прочитавших данную статью почерпнёт что-то новое и полезное для себя.
Причиной появления этой публикации стало нежелание больше молчать и просто смотреть, как интернет заполняют «всезнающие» программисты, которые учат новичков в нашей сфере забивать гвозди микроскопом, находя десятки аргументов в защиту своих методов! Потому, эта публикация направлена, скорее, на новичка постигающего программирование и задающего вопросы. Она является моим «правильным ответом»
Итак, что же такое Исключение (Exception)?
Посмотрите в свой код. Можете ли вы к каждому исключению дописать «но ведь это невозможно» или «но это же исключено»? Думаю, мало кто сможет честно ответить «да». Если ваш ответ «нет» — значит часть исключений на самом деле не являются таковыми, просто вы использовали этот механизм, потому как вам показалось это более удобным. То самое «удобство» такого подхода будет рассмотрено далее.
Кто же должен определять, какие ситуации программа исключает, а какие нет?
Все исключения могут быть продиктованы только заданием или здравым смыслом, и ничем или никем иным. Исключение не определяется ни типом данных, ни их источником, хотя нередко можно услышать или прочитать в «умных» статьях: «Неправильный клиентский ввод не может быть исключением»… не верьте! Вот, просто, не надо в такое верить.
Вы можете в задании получить вполне разумное исключение неверного клиентского ввода: «С системой будут работать специально обученные менеджеры нашей компании, потому ввод неправильных данных исключён» или «Менеджер будет загружать в систему письма, которые уже прошли проверку правильности формата, поэтому формат всегда будет именно такой». Вот теперь заказчик сам вам сказал, где следует породить исключение в написанной для него программе (и ничего страшного, что это клиентский ввод). Разумеется, если речь всё же идёт о неком продукте, а не библиотеке, программу не надо просто ронять. Пускай на верхнем уровне висит обработчик исключений и превращает все необработанные исключения в ошибки, сохраняет данные и деликатно завершает выполнение (или передаёт управление основному модулю, если ошибка не в нём).
Но, как и обычно, не забываем читать между строк и уточнять задание. Если вас просят сохранить файл, уточните, возможна ли ситуация, что файл не сохранится. А если решили не уточнять, тогда не исключайте такую вероятность, а реализуйте реакцию на это событие. Ваш код не должен ни о чём умалчивать.
Или предусмотрите, или исключите.
Почему любое лишнее Исключение является вредным для кода?
Не раз сталкивался с ситуацией, когда отрицательный результат выполнения функции возвращали в виде исключения, хотя такой результат был предусмотрен самой задачей. На этот счёт слышал разные пояснения:
- Не передавать же по всей цепочке вызовов флаг завершения
- Мне надо передать данные, собранные до получения отрицательного ответа
- Функция может вернуть отрицательный результат по трём причинам. Так проще передать эту причину
- множество других доводов...
Почему же так не надо делать? Да потому, что:
- Вы не сможете смело использовать уже написанные методы в других местах, ведь они могут порождать неожиданные исключения;
- GOTO зло — потому что путает код, передавая управление в произвольную точку. Не следует думать, что передача управления, перепрыгивая произвольное количество вызовов в стеке, меньше путает ваш код, чем GOTO;
- Кому-то, а возможно и вам самим, потом надо будет что-то исправить или дописать в написанном коде. Не следует считать, что через 2 года вы влёт вспомните, что этот модуль системы для отрицательных ответов использует исключения. То есть, вам придётся вникать… и вникать не только в код, но и во все «необычности» подхода.
Не стал включать в список выше такие аргументы как «это правило хорошего тона» и «давайте всё использовать по назначению», итак написано уже достаточно.
Заключение
Старался не вдаваться лишние подробности и в каждое предложение вкладывать максимум смысла. Надеюсь у меня это получилось, и читая эти строки, вы думаете: «пять минут, а столько нового!» Ну что же, надеюсь это так.
Напоследок хотелось бы сказать, что не следует изворачиваться под давлением факторов, сроков и «так же проще», и писать неправильный код, зато быстро.
Совершенство и отказоустойчивость нашего кода и определяет наш профессионализм.