Страницы

Поиск по вопросам

понедельник, 2 декабря 2019 г.

Чем плох перехват всех исключений разом?

#c_sharp #исключения


Является ли антипаттерном  перехват всех исключений разом? 

Чем плох такой подход:

try {
    foo();
} catch (Exception e) {
    // handle <-- разумеется, тут реальная обработка, а не подавление исключений
}


Не указывая какие конкретно исключения я хочу обработать.

Допустим, у меня в try...catch обёрнут код работающий с файловой системой, для конкретики
- копирование файла.

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

Я слышал, что можно обобщить эксепшены и не писать каждый раз PathTooLongException,
DirectoryNotFoundException и DirectoryNotFoundException, а один раз обработать IOException,
от которого они все наследуются. Это помогает сократить количество блоков catch, но
не сильно (в примере с File.Copy - можно сократить на 4, всего 8). Правильный ли это
подход или тут тоже есть свои нюансы?
    


Ответы

Ответ 1



Вы описываете какое то совсем малюсенькое правило и возводите его в абсолют. К счастью, в природе нет таких жестких правил, и, при разработке, программисту как в данном случае, так и во всех других случаях, следует пользоваться также головой. Например, первый вопрос при обработке исключения, который может возникнуть - а сделал ли вызываемый метод свою работу? Или, если вы по таймеру вызываете сторонний сервис, то куда бы выше вы бы хотели пробросить исключение? Интересует ли вызывающий код вообще проблемы вызванной функции? Например, если вы по таймеру делаете одно и то же, просто сторонний сервис то работает, то не работает, то имеет смысл факт проблем с ним писать в лог и, возможно, кого то оповестить о проблемах, не важно каких, сеть отвалилась или сервер возвращает 500 - таймеру это не интересно. Но если вы копируете файлы, то, наверно, вызывающему коду будет интересно узнать о результате операции. В таком случае, если и ловить все исключения, то только для того, чтобы залогировать и оправить исключение дальше, выше по стеку. По поводу того, какие типы перехватывать исключений - все просто. Если вам есть разница между FileNotFoundException и DirectoryNotFoundException в вашей логике, то перехватывайте их отдельными обработчиками. Если разницы нет, и вас не интересует специфика проблемы, только её наличие, то перехватывайте одним.

Ответ 2



Перехватывают исключения по типам когда ты хочешь запустить отдельный сценарий для конкретного исключения. Допустим если у тебя FileNotFound exception и только в этом случае ты хочешь вернуть FileNotFoundResult, в все остальные случаи ты хочешь просто сделать лог: try { foo(); } catch (FileNotFound exception) { return new FileNotFoundResult() } catch(Exception ex){ logger.Log(ex.Message) } Так как все исключения наследуются от родительского класса Exception, то его catch statement нужно указывать в самом низу

Комментариев нет:

Отправить комментарий