Обработка ошибок?

Функция выполняет некоторую работу и возвращает результат, но в ходе работы может что-то пойти не так, и результат не будет получен. Вопроса, на самом деле, два:

1. что вернуть при неудачном раскладе?

2. как сообщить об ошибке?


Например, функция рассчитывает сумму двух положительных чисел, на вход передали 3 и -2.
  • Вопрос задан
  • 3595 просмотров
Пригласить эксперта
Ответы на вопрос 7
Ексепшен выкинуть, разумеется. Пусть тот, кто вызвал с фиговыми параметрами, сам разбирается что с этим делать.
Ответ написан
Рассмотрим другой пример: процедура поиска чего-нибудь. Мы ищем ищем, и не можем найти. Каким способом сообщить причину неудачного поиска? Вернуть в этой ситуации можно пустой список или null.

Если мы ничего не нашли, то выводим просто пустой список. И это логично, Вы ведь искали что-то по корректному списку, ничего не нашли, поэтому вернули пустой список.
Если же при попытки поиска по данным произошло что-то нештатное (БД отвалилась, файл перестал читаться и т.д.), то нужно выкидывать исключение, ловить его и обрабатывать. Пользователю тоже желательно показать. что произошла ошибка.
Ответ написан
Комментировать
7workers
@7workers
Макконел рекомендует (насколько я помню) — если возможно, разделяйте функцию на две например isSearchRequestValid() и doSearch() если что-то пошло не так в doSearch() то это эксепшн, но пользователь получает «Server error» а разработчик получает алерт с трэйсом.
Ответ написан
Комментировать
afiskon
@afiskon
Если вы пишите на чем-то вроде Haskell или Scala и функция чистая, то в случае ошибки должны возвращать None, а в случае успеха Some(X). То есть, использовать тип Maybe или Option. Если функция не чистая или вы пишите на неправильном языке, нужно бросать исключение.
Ответ написан
Комментировать
EugeneOZ
@EugeneOZ
Вам тут все понасоветуют выкидывать эксепшены, однако это вопрос очень холиварный. Я в этом вопрос не поддерживаю любимого мною Роберта Мартина, а поддерживаю Google. Эксепшены нужны только тогда, когда случилась катастрофа и если не остановить программу, судьба планеты окажется в опасности. Если не планеты, то пользователя. В остальных случаях функция не имеет права решать, что пришло время полностью остановить работу программы, а значит бросать «исключение» без исключительных ситуаций нельзя.

Конкретно в Вашем примере я бы сгенерил warning и вернул false.
Ответ написан
Если произошла ошибка (в том числе и при поиске), то безусловно исключение (если они есть). Т.е. в случае с поиском, если найти не можем из-за ошибки соединения с БД или некорректных условий поиска.
А если найти не можем из-за того, что элемента нет и это нормальная штатная ситуация, то использовать специальное возвращаемое значение. В языках с динамической типизацией это как правило None, null или подобный тип. Если None может храниться в коллекции и является допустимым возвращаемым значением, то, например в питоне, часто создают класс с именем тип NotFoundError и возвращают тип класса. Он гарантированно не является валидным значением.
В языках со статической типизацией используют либо что-то вроде boost::optional т.е. структуры из значения и флага, либо возвращают указатель/итератор для которого есть специальное пустое значение.
Ответ написан
Комментировать
@lesha_penguin
Не надо «форсить» ошибку там, где ее нет. Пустой результат — тоже результат. Но бывают и ошибки. Самый лучший пример как и в каких случаях это делается «по-взрослому» это… внезапно… сервер баз данных. Самый простой и очень понятный пример когда ошибка, а когда пустой результат:

Если вы пошлете корректный запрос, например, «SELECT * FROM table WHERE field1=100» но в таблице нет таких записей в которых поле field1=100 сервер вам корректно вернет пустой ответ.

Однако, если вы в этот же сервер пошлете заведомо ошибочный запрос, вроде «SELECT * FROM тут_нет_такой_таблицы WHERE и_поля_тоже_нет='всем буй'» сервер вам вернет ошибку. Точно, также ошибка вам вернется, если на сервере произошел таймаут, дедлок, или что-то подобное.

Примерно, такого поведения пользователь ждет и от вашего приложения. Не надо ставить людей в «когнитивный диссонанс», принцип наименьшего удивления — хороший принцип.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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