Обработка исключений – это хороший способ?

Мы боремся с политикой, чтобы правильно обрабатывать исключения в нашем приложении. Вот наши цели для него (обобщены):

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

Мы вышли с решением, которое включает в себя общее специфическое исключение приложения и работает в этом fragmentе кода:

try { // Do whatever } catch(ArgumentNullException ane) { // Handle, optinally log and continue } catch(AppSpecificException) { // Rethrow, don't log, don't do anything else throw; } catch(Exception e) { // Log, encapsulate (so that it won't be logged again) and throw Logger.Log("Really bad thing", e.Message, e); throw new AppSpecificException(e) } 

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

У меня не так много опыта с шаблонами обработки исключений … Является ли это хорошим способом решения наших задач? Имеются ли какие-либо серьезные недостатки или большие красные предупреждения?

Примечание. Одним из недостатков этого является то, что после первого улова вы теряете способность обрабатывать конкретное исключение (если вы вызываете метод, который вызывает другой метод, а второй – исключение, которое вы не можете обработать), но Я обнаружил, что никогда не делал этого … Я занимаюсь только исключениями с одним уровнем глубины …

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

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

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

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

Только поймайте исключение для его обработки (например, для его регистрации) или добавьте контекстную информацию.

Это довольно распространенный подход для решения проблемы обработки исключений (от более конкретных до менее конкретных).

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

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

Первый вариант решения проблемы трассировки стека:

 class AppSpecificException : ApplicationException { public string SpecificTrace { get; private set; } public string SpecificMessage { get; private set; } public AppSpecificException(string message, Exception innerException) { SpecificMessage = message; SpecificTrace = innerException.StackTrace; } } 

Я должен был написать пример, чтобы понять вопрос и проверить проблему stacktrace, это код для меня, обратите внимание на метод button2_click, наконец, в моем текстовом поле отображаются строка сбоя и stacktrace:

  private String internalValue; private void Operation1(String pField) { if (pField == null) throw new ArgumentNullException("pField"); internalValue = pField; } private void Operation2(Object pField) { if (pField == null) throw new ArgumentNullException("pField"); internalValue = Convert.ToInt32(pField).ToString(); } private void Operation3(String pField) { if (pField == null) throw new ArgumentNullException("pField"); internalValue = pField; Operation2(-1); } /// AppSpecificException. private void button1_Click(object sender, EventArgs e) { try { Operation1("One"); Operation2("Two"); Operation3("Three"); MessageBox.Show(internalValue); } catch (ArgumentNullException ex) { textBoxException.Text = ex.Message + (char) 13 + (char) 10 + ex.StackTrace; } catch (AppSpecificException ex) { //textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace; throw; } catch (Exception ex) { textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace; throw new AppSpecificException("crash", ex); } } private void button2_Click(object sender, EventArgs e) { try { button1_Click(sender, e); } catch (AppSpecificException ex) { textBoxException.Text = ex.SpecificMessage + (char) 13 + (char) 10 + ex.SpecificTrace; } } 

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

Я бы рекомендовал больше подумать о том, какие шаблоны вы хотите использовать для «раздачи»,

Если ваши шаблоны обработки сводятся к логарифму или реверту, тогда вновь занесенная ошибка будет зарегистрирована. Поэтому, в конце концов, это просто журнал ошибок. Если вы используете ASP.NET, используйте elmah, поэтому, по крайней мере, ваш код не покрывается табличкой котлов try / catch-and-log.

Есть только несколько способов «обрабатывать» ошибки, которые не заканчиваются простым протоколированием.

Re-попробовать. (Остерегайтесь бесконечных циклов)

Подождите и повторите попытку.

Попробуйте использовать другую, но эквивалентную технику (не удается подключиться к http? Попробуйте подключиться по https).

Установите отсутствующие условия (создайте папку, в которой было выбрано FolderNotFoundException)

Игнорируйте ошибку – подумайте дважды об этом, это имеет смысл только тогда, когда ошибка не является действительно проблемой, например, если сторонняя библиотека предупреждает вас о состоянии, которое не применяется.

Хорошим решением для обработки исключений является использование Interception. Однако вы должны проверить, может ли этот шаблон применяться к вашему приложению в зависимости от архитектуры: для перехвата требуется контейнер.

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

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

Перехват Unity: http://msdn.microsoft.com/en-us/library/dd140045.aspx

  • Как поймать ВСЕ исключения / сбои в приложении .NET
  • Обработка исключений в запросах ajax JSF
  • Обработка исключений Async с void
  • Каков правильный способ повторного выброса исключения в C #?
  • JAX-RS с использованием механизмов исключения
  • Почему порядок имеет значение при перехвате исключений?
  • Когда я должен действительно использовать noexcept?
  • Насколько медленны исключения Java?
  • Обработка исключительных ситуаций ASP.NET Core Web API
  • VS2010 не показывает необработанное сообщение об исключении в приложении WinForms в 64-разрядной версии Windows
  • Служба имеет нулевые приложения (неинфраструктурные) конечные точки
  • Interesting Posts

    Как я могу улавливать и обрабатывать данные из ответов XHR с помощью casperjs?

    Почему я получаю внутреннюю ошибку переполнения стека при минимизации и восстановлении окна виртуальной машины MS-DOS?

    Последняя непустая ячейка (столбец) в данной строке; Excel VBA

    Как заставить Thunderbird загружать все электронные письма с помощью IMAP?

    Личные имена в глобальном приложении: что хранить

    Создание якорных комментариев программным способом в Документах Google

    mysqli_stmt :: bind_param (): Число элементов в строке определения типа не совпадает с числом переменных привязки

    Необходимо усечь переменную% username% в Windows 7 до семи символов

    Как я могу поменять клавиши Ctrl и Fn на корпоративном компьютере?

    Проблема с Windows XP Internet

    Zsh говорит «не найдено совпадений» при попытке загрузить видео с помощью youtube-dl

    Плюсы / минусы баз данных на основе документов и реляционных баз данных

    Как запретить пользователю вводить текст в textarea после достижения максимального предела персонажа

    Использование ключевого слова var в C #

    Закладки Google Chrome в закладках Google

    Давайте будем гением компьютера.