Попробуйте Catch блоков внутри или снаружи функций и обработки ошибок - PullRequest
24 голосов
/ 22 января 2010

Это больше вопрос программирования общего назначения, чем языка. Я видел несколько аппарочей, чтобы попытаться поймать.

Во-первых, вы делаете любую необходимую предварительную обработку данных, вызываете функцию с соответствующими аргументами и переносите ее в блок try / catch.

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

Третий - комбинация с попыткой перехвата вне функции и внутри. Однако если функция try catch что-то перехватывает, она выдает другое исключение для блока try catch вне функции перехвата.

Есть мысли о плюсах / минусах этих методов контроля ошибок или есть ли принятый стандарт? Мои навыки ниндзя по поиску не помогли мне найти точные данные об этом.

Ответы [ 6 ]

18 голосов
/ 22 января 2010

Как правило, исключение должно быть перехвачено, только если оно действительно может быть обработано.

Нет смысла отлавливать исключение ни для каких целей, кроме как для его регистрации. Исключением является то, что исключения должны быть перехвачены на «верхнем уровне», чтобы их можно было регистрировать Весь другой код должен позволять исключениям распространяться на код, который их регистрирует.

4 голосов
/ 22 января 2010

Я думаю, что лучший способ думать об этом с точки зрения состояния программы. Вы не хотите, чтобы неудачная операция повредила состояние программы. В этом документе описывается понятие "исключительная безопасность".

В общем, вам сначала нужно решить, какой уровень безопасности исключений должна гарантировать функция. Уровни

  • Базовая гарантия
  • Сильная гарантия
  • Гарантия NoThrow

Основная гарантия просто означает, что при возникновении исключения или другой ошибки не происходит утечка ресурсов, строгая гарантия говорит о том, что состояние программы откатывается до исключения, а методы nothrow никогда не генерируют исключения.

Я лично использую исключения, когда происходит непредвиденный сбой во время выполнения. Неожиданное для меня означает, что такой сбой не должен происходить при нормальном ходе операций. Время выполнения означает, что ошибка связана с состоянием какого-либо внешнего компонента вне моего контроля, а не из-за логических ошибок с моей стороны. Я использую ASSERT () для обнаружения логических ошибок и булевых возвращаемых значений для ожидаемых ошибок.

Почему? ASSERT не скомпилирован в код выпуска, поэтому я не обременяю своих пользователей проверкой ошибок на свои собственные ошибки. Вот для чего нужны юнит-тесты и ASSERTS. Логическое значение, потому что выдача исключения может дать неправильное сообщение. Исключения тоже могут быть дорогими. Если я выбрасываю исключения в ходе обычного выполнения приложения, то я не могу использовать отличную функцию исключения «Catch on thrown» отладчика MS Visual Studio, где я могу заставить отладчик прерывать программу в момент, когда any генерируется исключение, а не по умолчанию остановка только на необработанных (аварийных) исключениях.

Чтобы увидеть технику C ++ для базовой гарантии, воспользуйтесь Google "RAII" (Resource Acquisition is Initialiation). Это метод, в котором вы заключаете ресурс в объект, конструктор которого выделяет ресурс, а чей деструктор освобождает ресурс. Поскольку исключения C ++ разматывают стек, это гарантирует, что ресурсы освобождаются перед лицом исключений. Вы можете использовать эту технику для отката состояния программы перед лицом исключения. Просто добавьте метод «Фиксация» к объекту, и если объект не был зафиксирован до его уничтожения, запустите операцию «Откат», которая восстанавливает состояние программы в деструкторе.

2 голосов
/ 22 января 2010

Каждый «модуль» в приложении отвечает за обработку своих собственных входных параметров. Как правило, вы должны найти проблемы как можно скорее, а не передавать мусор в другую часть приложения и полагаться на них, чтобы они были исправлены. Хотя есть исключения. Иногда проверка входного параметра в основном требует переопределения того, что должен делать вызываемый объект (например, анализ целого числа) в вызывающей стороне. В этом случае обычно целесообразно попробовать операцию и посмотреть, работает она или нет. Более того, есть некоторые операции, которые нельзя предсказать их успех, не выполняя их. Например, вы не можете надежно проверить, можете ли вы записать файл перед записью в него: другой процесс может немедленно заблокировать файл после вашей проверки.

1 голос
/ 22 января 2010

Нет никаких действительно жестких и быстрых правил в отношении обработки исключений, с которыми я сталкивался, однако у меня есть ряд общих правил, которые я хотел бы применить.

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

Никогда не выбрасывайте исключение в блоке finally, вы потеряете исходное исключение и замаскируете реальную проблему с неважной ошибкой.

Кроме того, это зависит от функции, которую вы реализуете. Вы в цикле, должны ли быть повторены остальные пункты или весь список прерван?

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

0 голосов
/ 22 января 2010

Единственный вопрос по отлову исключений: «Есть ли несколько стратегий для достижения цели?»

Некоторые функции могут сознательно перехватывать определенные исключения и пробовать альтернативные стратегии в случае этих известных исключений.

Все остальные исключения будут выброшены.

Если нет альтернативных стратегий, исключение будет просто выдано.

Редко вы хотите, чтобы функция улавливала (и отключала) исключения. Исключение означает, что что-то не так. Приложение - в целом - должно знать о необработанных исключениях. Он должен, по крайней мере, регистрировать их и, возможно, делать еще больше: выключить или, возможно, перезапустить.

0 голосов
/ 22 января 2010

Я обычно рассматриваю, могу ли я, как вызывающий метод, использовать исключение каким-либо образом (например, для восстановления после него, применяя другой подход) или если оно не имеет значения и просто пошло не так, если возникнет исключение. Таким образом, в первом случае я объявлю метод для генерирования исключения, в то время как во втором я поймаю его внутри метода и не буду беспокоить вызывающего его.

...