Как правильно использовать исключения?

Решил разобраться в деталях как работают и как правильно использовать исключения. Проблема в том, что почти всегда можно обойтись if else, но иногда используются исключения, и я не могу понять в каких ситуациях что предпочтительнее. Волнует и вопрос производительности (почему бы их везде не понапихать?) и безопасности и "трушности" для C#, Ruby и C++ (как коррелирует с философией языка).
  • Вопрос задан
  • 5751 просмотр
Решения вопроса 1
xanep
@xanep
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 5
Тут достаточно просто все.
Исключения помогают проскочить участок кода при выполнении определенных условий.
Причем, при коде без вызовов функций - всегда можно заменить на if/else, но код будет многовложенным (один if в другом). Но такой код естественно давно никто не пишет.

А при коде с вызовом функций это становится и вовсе невозможно (нельзя начало if написать в одном методе, а закрывающую скобку в другом). И нам приходится всю цепочку if передавать по стеку вызовов вверх.

Идея же исключений такая:
1. У нас есть алгоритм, который должен работать по заданной схеме. Мы нигде на уровне выше не проверяем корректность возвращаемых значений или правильность выполнения уровня ниже - он должен выполниться правильно или не выполниться. Это условие рождается из понимания инкапсуляции - каждый отвечает за свой кусок кода.
2. Если в какой момент момент, метод (кусок кода), отвечающий за определенную функциональность понимает, что не может выполнить назначенную ему операцию - он сообщает об этом на уровень выше.
3. Уровень выше может обработать исключительную ситуацию, либо (если не знает как) - передать исключение еще уровнем выше по стеку вызовов.

Т.е. резюмирую: у нас есть код, который должен в 90% случаев обрабатываться по одному алгоритму и в 10% случаях могут возникать ситуации, когда этот алгоритм в одной конкретной части кода - пойдет по другому сценарию.
Т.е. ваша задача писать код именно таким образом, чтобы исключения были лишь подстраховкой, а не частью основного алгоритма.

Интересный момент реализации исключений в lisp: там можно выполнить код вызвавший исключение повторно (например попытаться подключиться к базе второй раз средствами самого исключения).
Ответ написан
Комментировать
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Ну приведу простой пример. У вас есть функция которая должна открывать соединение с базой данных/читать из файла/подключаться к сокету... словом любая функция возвращающая некий ресурс, при помощи которого в дальнейшем будет осуществляться доступ к чему-то там.

Функция должна вернуть какой-то результат, причем определенного типа. Что вы будете делать в случае ошибки? А как уведомить разработчика что именно пошло не так?

Для этого ввели механизм исключений. Если в функции что-то идет не так, можно сформировать исключение со всей имеющейся по ошибке информации и выбросить его.

Если вы используете конструкцию try/catch в использующем эту функцию коде, то вместо крэша у вас вызовется один из обработчиков catch (вы можете спускаться по иерархии классов, задавая различное поведение для разного рода ошибок), возможно произведете какие-то уточнения в данных, переспросите пользователя и программа продолжит работу совершенно нормально.
Ответ написан
if-elsе (switch) используется в случаях-
"если не так, то попробуем с другой стороны",
то есть, это выбор вариантов исполнения.
а exception-
"если не так, то никак (потому, что ....)",
то есть остановка исполнения, и старт каких либо заключительных действий (например, записать ошибку в лог и отправить пользователю красивую картинку/заглушку).
таким образом, "if" - это штатный режим, а а exception- аварийный
Ответ написан
Illivion
@Illivion
Отвечаю по C#. Исключение должно выбрасываться в любом случае, если метод не может выполнить задачу, которая ему назначена. Метод CreateUser() не смог создать пользователя? Исключение! Метод Connect() не смог подключиться за заданный интервал времени? Исключение. Если не ошибаюсь, так писал Рихтер.
Ответ написан
@alexanius
Эту конструкцию не следует пихать везде где попало. Во-первых срабатывание исключения - очень дорогая штука. Во-вторых этого не следует, например, делать в деструкторах. Это первое что в голову приходит. Может есть ещё какие-то случаи. Советую почитать что на эту тему пишет Мейрес. Вообще советую его почитать. Моё мнение - исключение должно кидаться если программа рушится и нужно полное обрушение как-то проконтролировать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы