Вопрос

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

Большинство блоков кода (если не все) находятся внутри блока try/catch, а внутри блока catch выдается новое исключение BaseApplicationException, которое, похоже, исходит из корпоративных библиотек.У меня здесь небольшие проблемы, так как я не вижу в этом выгоды.(Бросая другое исключение в любое время, когда происходит) один из разработчиков, который некоторое время использовал систему, сказал, что это потому, что этот класс отвечает за публикацию исключения (отправка электронных писем и тому подобное), но он не был слишком уверен в этом.Потратив некоторое время на изучение кода, я с уверенностью могу сказать, что все, что он делает, — это собирает информацию об окружающей среде и затем публикует ее.

Мой вопрос:- Разумно ли помещать весь код в блоки try { } catch { }, а затем генерировать новое исключение?И если да, то почему?В чем выгода?

Мое личное мнение таково, что было бы гораздо проще использовать HttpModule, подписаться на событие Error события Application и делать все необходимое внутри модуля.Если бы мы пошли по этому пути, пропустили бы мы что-нибудь?Есть недостатки?

Ваше мнение очень ценно.

Это было полезно?

Решение

Никогда1 catch (Exception ex).Период2.Невозможно справиться со всеми видами ошибок, которые вы можете обнаружить.

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

Несколько причин для этого, из головы:

  • Ловля и переброска обходятся дорого.
  • В конечном итоге вы потеряете трассировку стека
  • В вашем коде будет низкое соотношение сигнал/шум.

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

Чтобы обрабатывать неперехваченные исключения, прослушивайте соответствующие события.При работе с WinForms вам нужно будет прислушиваться к System.AppDomain.CurrentDomain.UnhandledException, и - если вы делаете Threading - System.Windows.Forms.Application.ThreadException. Для веб-приложений существуют аналогичные механизмы (System.Web.HttpApplication.Error).

Что касается переноса исключений платформы в (не)специфичные для вашего приложения исключения (т.е. throw new MyBaseException(ex);):Совершенно бессмысленно и неприятный запах.4


Редактировать

1 Никогда — это очень резкое слово, особенно когда речь идет о технике, как отметил @Chris в комментариях.Я признаю, что был очень принципиальным, когда впервые написал этот ответ.

2,3 Видеть 1.

4 Если вы не принесете ничего нового, я все равно поддержу это.Если вы поймали Exception ex как часть метода, который, как вы знаете, может потерпеть неудачу по-разному, я считаю, что текущий метод должен отражать это в своей сигнатуре.И, как вы знаете, исключения не являются частью сигнатуры метода.

Другие советы

Если я правильно читаю вопрос, я бы сказал, что реализация try/catch, которая перехватывает исключения (вы не упоминаете - она ​​перехватывает все исключения или только определенное?) и выдает другое исключение, это вообще плохая вещь .

Недостатки:

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

Если вы перехватываете Exception, вы рискуете замаскировать критические исключения, такие как OutOfMemory или StackOverflow, менее критическими исключениями и, таким образом, оставить процесс работающим там, где, возможно, его следовало бы прервать.

Возможные преимущества:

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

Однако почти во всех случаях это неприятный запах, и его следует использовать с осторожностью.

Как правило, вам следует ловить исключение только тогда, когда в этом месте есть что-то реалистичное, например, восстановление, откат, переход к плану Б и т. д.Если вы ничего не можете с этим поделать, просто позвольте ему пройти вверх по цепочке.Вам следует перехватывать и генерировать новое исключение только в том случае, если в этом месте имеются конкретные и полезные данные, которые могут дополнить исходное исключение и, следовательно, помочь в отладке.

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

Вот интересный пост о том, как использовать HttpModule для обработки исключений: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to-troubleshoot-your-asp-net-application.aspx и http://blogs.msdn.com/rahulso/archive/2008/07/18/asp-net-how-to-write-error-messages-into-a-text-file-using-a-simple-httpmodule. aspx

Проверить ЭЛЬМА.Он делает то, о чем вы говорите.Очень хорошо.

Когда я создаю библиотеки, я стараюсь всегда предоставлять меньшее количество исключений для обработки вызывающими объектами.Например, представьте себе компонент репозитория, который подключается к базе данных sql.Существует ТОННЫ исключений, от исключений клиента sql до исключений недопустимого приведения, которые теоретически могут быть выброшены.Многие из них четко документированы и могут быть учтены во время компиляции.Итак, я перехватываю как можно больше из них, помещаю их в один тип исключения, скажем, RepositoryException, и позволяю этому исключению свернуть стек вызовов.

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

Конечно, с этим есть некоторые проблемы.В частности, если вызывающий объект может обработать некоторые из этих исключений, ему придется просмотреть RepositoryException, а затем включить тип внутреннего исключения для его обработки.Это менее чисто, чем наличие одного блока catch для одного типа исключения.Однако я не думаю, что это такая уж большая проблема.

Похоже, что выброшенное исключение не должно было быть реализовано как исключение.

В любом случае, я бы сказал, что, поскольку это BaseApplicationException является общим универсальным исключением, было бы хорошо создавать исключения, более специфичные для контекста.Поэтому, когда вы пытаетесь получить объект из базы данных, вам может потребоваться исключение EntityNotFoundException.Таким образом, при отладке вам не придется искать внутренние исключения и трассировки стека, чтобы найти реальную проблему.Если это исключение BAseApplicationException собирает информацию об исключении (например, отслеживает внутреннее исключение), то это не должно быть проблемой.

Я бы использовал HttpModule только тогда, когда не мог приблизиться к тому, где на самом деле происходят исключения в коде.На самом деле вам не нужно, чтобы событие HttModule OnError представляло собой гигантский оператор переключения, зависящий от информации об ошибке BaseApplicationException.

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

По моему опыту, поймайте исключение, добавьте ошибку в объект Сервер (?).Это позволит .NET делать то, что ему нужно, а затем отображать ваше исключение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top