поддерживая код моего коллеги даже от того, кто утверждает, что он является старшим разработчиком, я часто вижу следующий код:
try
{
//do something
}
catch
{
//Do nothing
}
или иногда они записывают информацию журнала в файлы журнала, например, следующий try catch
блок
try
{
//do some work
}
catch(Exception exception)
{
WriteException2LogFile(exception);
}
Мне просто интересно, является ли то, что они сделали, лучшей практикой? Это сбивает меня с толку, потому что, по моему мнению, пользователи должны знать, что происходит с системой.
Пожалуйста, дайте мне совет.
NullReference
илиArgumentNull
это не является частью потока приложения), это означает, что есть ошибка, которую необходимо исправить, поэтому регистрация их поможет намного быстрее отладить ваш код.Ответы:
Моя стратегия обработки исключений:
Чтобы поймать все необработанные исключения , подключив к
Application.ThreadException event
, решите:Тогда я всегда прилагаю каждый кусок кода , который выполняется снаружи в
try/catch
:Тогда я прилагаю в «попробовать / поймать»
ApplicationException("custom message", innerException)
чтобы следить за тем, что на самом деле произошлоКроме того, я стараюсь правильно сортировать исключения . Есть исключения, которые:
finally
раздел во времяTreeView
заполнения)пользователю все равно, но важно знать, что произошло. Поэтому я всегда их регистрирую:
Хорошей практикой является разработка некоторых статических методов для обработки исключений. в обработчиках ошибок верхнего уровня приложения.
Я также заставляю себя попытаться:
Итак, наконец:
Плохой:
Бесполезный:
Попытка, наконец, без улова совершенно допустима:
Что я делаю на высшем уровне:
Что я делаю в некоторых называемых функциях:
Есть много общего с обработкой исключений (Custom Exceptions), но этих правил, которые я стараюсь помнить, достаточно для простых приложений, которые я делаю.
Вот пример методов расширений для удобной обработки обработанных исключений. Они реализованы таким образом, что их можно объединить в цепочку, и очень легко добавить собственную обработанную обработанную исключительную ситуацию.
источник
catch(Exception ex) { throw ex; }
в C # хуже, чем избыточный (независимо от того, какой тип исключения вы ловите). Для отбрасывания используйтеthrow;
. В первом случае исключение будет выглядеть так, как будто оно возникло у вас,throw ex
тогда как во втором случае оно будет правильно исходить из исходногоthrow
утверждения.Application.ThreadException
событие и заключаете каждое исключение вcatch(Exception ex) {ex.Log(ex);}
. Я бы, вероятно, согласился с тем, что первое является отличной практикой, но второе добавляет риск дублирования ваших журналов ошибок и скрывает, что произошло исключение. Такжеthrow ex
очень, очень плохо.Application.ThreadException
мероприятие, я не знал об этом, очень полезно.Лучшая практика заключается в том, что обработка исключений никогда не должна скрывать проблемы . Это означает, что
try-catch
блоки должны быть крайне редкими.Есть 3 обстоятельства, при которых использование
try-catch
имеет смысл.Всегда имейте дело с известными исключениями как можно ниже. Однако, если вы ожидаете исключения, обычно лучше сначала проверить его. Например, синтаксический анализ, форматирование и арифметические исключения почти всегда лучше обрабатываются сначала логическими проверками, чем конкретными
try-catch
.Если вам нужно что-то сделать для исключения (например, войти в систему или откатить транзакцию), перезапустите исключение.
Всегда обрабатывайте неизвестные исключения как можно выше - единственный код, который должен использовать исключение, а не повторно генерировать его, должен быть пользовательским интерфейсом или общедоступным API.
Предположим, вы подключаетесь к удаленному API, здесь вы знаете, что ожидаете определенных ошибок (и в этих обстоятельствах есть что-то, что нужно), так что это случай 1:
Обратите внимание, что другие исключения не обнаруживаются, так как они не ожидаются.
Теперь предположим, что вы пытаетесь сохранить что-то в базе данных. Мы должны откатить его обратно, если он потерпит неудачу, поэтому у нас есть случай 2:
Обратите внимание, что мы перебрасываем исключение - код выше должен знать, что что-то не получилось.
Наконец, у нас есть пользовательский интерфейс - здесь мы не хотим иметь полностью необработанные исключения, но мы не хотим их скрывать. Здесь у нас есть пример случая 3:
Тем не менее, большинство API или интерфейсов пользовательского интерфейса имеют общие способы выполнения случая 3. Например, ASP.Net имеет желтый экран ошибок, который выводит подробности исключений, но его можно заменить на более общее сообщение в производственной среде. Следование этим рекомендациям является наилучшей практикой, потому что это экономит вам много кода, а также потому, что регистрация ошибок и их отображение должны быть решениями конфигурации, а не жестко заданными.
Все это означает, что случай 1 (известные исключения) и случай 3 (одноразовая обработка пользовательского интерфейса) имеют лучшие образцы (избегайте обработки ожидаемой ошибки или ручной ошибки в пользовательском интерфейсе).
Даже случай 2 можно заменить лучшими шаблонами, например областями транзакций (
using
блоки, которые откатывают любую транзакцию, не зафиксированную во время блока), затрудняют для разработчиков ошибочную модель оптимальной практики.Например, предположим, у вас есть крупномасштабное приложение ASP.Net. Регистрация ошибок может быть через ELMAH , отображение ошибок может быть информативным YSoD локально и хорошим локализованным сообщением в производстве. Все соединения с базой данных могут осуществляться через области транзакций и
using
блоки. Вам не нужен ни одинtry-catch
блок.TL; DR: Лучшая практика - вообще не использовать
try-catch
блоки.источник
try-catch
- он может (очень редко) быть полезным, и я не утверждаю, что вы никогда не должны его использовать, но в 99% случаев есть лучший способ.Исключением является ошибка блокировки .
Прежде всего, лучшая практика должна заключаться в том, чтобы не выдавать исключения для любых ошибок, если только это не ошибка блокировки .
Если ошибка блокирует , то сгенерируйте исключение. Как только исключение уже выброшено, его не нужно скрывать, потому что оно исключительное; сообщите пользователю об этом (вам следует переформатировать все исключение, чтобы пользователь получил что-то полезное в пользовательском интерфейсе).
Ваша задача как разработчика программного обеспечения состоит в том, чтобы постараться предотвратить исключительный случай, когда какой-либо параметр или ситуация во время выполнения могут закончиться исключением. То есть исключения не должны быть отключены, но их следует избегать .
Например, если вы знаете, что некоторые целочисленные данные могут иметь неправильный формат, используйте
int.TryParse
вместоint.Parse
. Есть много случаев, когда вы можете сделать это вместо того, чтобы просто сказать «если это не удастся, просто выбросить исключение».Бросать исключения стоит дорого.
Если, в конце концов, выдается исключение, а не записывать исключение в журнал после того, как оно было сгенерировано, одна из лучших рекомендаций - перехватить его в обработчике исключений первого шанса . Например:
Моя позиция заключается в том, что локальные try / catches лучше подходят для обработки особых случаев, когда вы можете перевести исключение в другое или если вы хотите «отключить» его для очень, очень, очень, очень, очень особого случая (ошибка библиотеки выбрасывание несвязанного исключения, которое необходимо отключить, чтобы обойти всю ошибку).
Для остальных случаев:
Отвечая на @thewhiteambit на некоторый комментарий ...
@ thewhiteambit сказал:
Прежде всего, как исключение не может быть даже ошибкой?
null
то время как объект ожидался => исключениеМы могли бы перечислить 1 000 случаев, когда выдается исключение, и в конце концов, любой из возможных случаев будет ошибкой .
Исключением является ошибка, потому что в конце дня это объект, который собирает диагностическую информацию - у него есть сообщение, и это происходит, когда что-то идет не так.
Никто не бросил бы исключение, когда нет исключительного случая. Исключения должны блокировать ошибки, потому что после их появления, если вы не попытаетесь использовать try / catch и исключения для реализации потока управления, это означает, что ваше приложение / служба остановит операцию, которая вошла в исключительный случай .
Кроме того, я предлагаю всем проверить парадигму быстрого отказа, опубликованную Мартином Фаулером (и написанную Джимом Шором) . Именно так я всегда понимал, как обрабатывать исключения, даже до того, как попал в этот документ некоторое время назад.
Обычно исключения сокращают некоторый поток операций, и они обрабатываются, чтобы преобразовать их в понятные человеку ошибки. Таким образом, кажется, что исключение на самом деле является лучшей парадигмой для обработки случаев ошибок и работы над ними, чтобы избежать полного сбоя приложения / службы и уведомить пользователя / потребителя, что что-то пошло не так.
Больше ответов о проблемах @thewhiteambit
Если ваше приложение может работать в автономном режиме без сохранения данных в базе данных, вы не должны использовать исключения , так как использование потока управления
try/catch
рассматривается как анти-шаблон. Автономная работа - это возможный вариант использования, поэтому вы реализуете поток управления, чтобы проверить, доступна ли база данных или нет, и вы не ждете, пока она не станет недоступной .Разборе вещь также ожидаемый случай ( не исключительный случай ). Если вы ожидаете этого, вы не используете исключения для управления потоком! , Вы получаете метаданные от пользователя, чтобы узнать, какова его / ее культура, и для этого вы используете средства форматирования! .NET также поддерживает эту и другие среды, и это исключение, поскольку следует избегать форматирования чисел, если вы ожидаете, что ваше приложение / служба будет зависеть от конкретной культуры .
Эта статья просто мнение или точка зрения автора.
Так как Википедия может быть просто мнением автора (ов) статьи, я бы не сказал, что это догма , но проверь, что в статье « Кодирование за исключением» говорится где-то в некотором абзаце:
Это также говорит где-то:
Неправильное использование исключения
Честно говоря, я считаю, что программное обеспечение не может быть разработано без серьезного рассмотрения вариантов использования. Если вы это знаете ...
... вы не будете использовать исключения для этого . Вы бы поддержали эти варианты использования, используя регулярный поток управления.
И если какой-то неожиданный вариант использования не будет рассмотрен, ваш код быстро потерпит неудачу, потому что он выдаст исключение . Правильно, потому что исключение - исключительный случай .
С другой стороны, и, наконец, иногда вы покрываете исключительные случаи, выбрасывая ожидаемые исключения , но вы не бросаете их для реализации потока управления. Вы делаете это потому, что хотите уведомить верхние уровни о том, что вы не поддерживаете какой-либо вариант использования или ваш код не работает с некоторыми заданными аргументами или данными / свойствами среды.
источник
Единственный раз, когда вы должны беспокоить своих пользователей о том, что произошло в коде, это если они могут или должны что-то сделать, чтобы избежать этой проблемы. Если они могут изменить данные в форме, нажмите кнопку или измените настройку приложения, чтобы избежать проблемы, а затем сообщите об этом. Но предупреждения или ошибки, которые пользователь не может избежать, просто заставляют его потерять доверие к вашему продукту.
Исключения и журналы предназначены для вас, разработчика, а не вашего конечного пользователя. Понимание того, что нужно делать, когда вы ловите каждое исключение, гораздо лучше, чем просто применять какое-то золотое правило или полагаться на систему безопасности всего приложения.
Бездумное кодирование - ЕДИНСТВЕННЫЙ вид неправильного кодирования. Тот факт, что вы чувствуете, что есть что-то лучшее, что может быть сделано в этих ситуациях, показывает, что вы вкладываетесь в хорошее кодирование, но избегайте попыток запечатлеть какое-то общее правило в этих ситуациях и понимаете причину чего-то, что бросить в первую очередь, и что Вы можете сделать, чтобы оправиться от этого.
источник
Я знаю, что это старый вопрос, но никто здесь не упомянул статью MSDN, и это был документ, который действительно прояснил это для меня, MSDN имеет очень хороший документ по этому вопросу, вы должны ловить исключения, когда выполняются следующие условия:
Я бы посоветовал прочитать весь раздел « Исключения и обработка исключений », а также рекомендации по исключениям .
источник
Лучший подход - второй (тот, в котором вы указываете тип исключения). Преимущество этого заключается в том, что вы знаете, что в вашем коде могут возникать исключения такого типа. Вы обрабатываете этот тип исключения, и вы можете возобновить. Если возникло какое-либо другое исключение, это означает, что что-то не так, что поможет вам найти ошибки в вашем коде. Приложение в конечном итоге завершится сбоем, но вы поймете, что есть что-то, что вы пропустили (ошибка), которую необходимо исправить.
источник
За исключением, я пробую следующее:
Во-первых, я ловлю особые типы исключений, такие как деление на ноль, операции ввода-вывода и так далее, и пишу код в соответствии с этим. Например, деление на ноль, в зависимости от происхождения значений, которые я мог бы предупредить пользователя (например, простой калькулятор в том, что при среднем вычислении (не аргументах) получается деление на ноль) или молча обработать это исключение, ведя журнал это и продолжить обработку.
Затем я пытаюсь поймать оставшиеся исключения и зарегистрировать их. Если возможно, разрешите выполнение кода, в противном случае предупредите пользователя о возникновении ошибки и попросите его отправить сообщение об ошибке по почте.
В коде что-то вроде этого:
источник
0
решать, предварительно проверив числитель, а не atry-catch
. И зачем ловитьException
здесь дженерик ? Вам лучше позволить ошибке всплыть, чем иметь дело с ней здесь во всех случаях, когда вы этого не ожидаете.Второй подход хорош.
Если вы не хотите показывать ошибку и вводить пользователя в заблуждение, показывая исключительную ситуацию времени исполнения (т. Е. Ошибку), которая не связана с ними, просто зарегистрируйте ошибку, и техническая команда может найти проблему и устранить ее.
Я рекомендую вам пойти на второй подход для всего вашего приложения.
источник
catch
блоки всегда должны либо вызыватьthrow
всплывающее исключение, либо возвращать что-либо / отображать что-то, что говорит пользователю о том, что действие не выполнено. Вы хотите позвонить в службу поддержки, когда они не могут сохранить, что бы это ни было, а не через 6 месяцев, когда они пытаются найти его и не могут его найти.Оставить пустой блок улова - хуже. Если есть ошибка, лучший способ ее исправить:
источник
Для меня обработка исключений может рассматриваться как бизнес-правило. Очевидно, что первый подход неприемлем. Второй вариант лучше, и он может быть на 100% правильным, если контекст так говорит. Например, сейчас вы разрабатываете надстройку для Outlook. Если надстройка создает необработанное исключение, пользователь Outlook теперь может знать об этом, поскольку Outlook не будет самоуничтожаться из-за сбоя одного из плагинов. И вам трудно понять, что пошло не так. Поэтому второй подход в данном случае, на мой взгляд, является правильным. Помимо регистрации исключения, вы можете решить отобразить сообщение об ошибке для пользователя - я считаю это бизнес-правилом.
источник
Рекомендуется генерировать исключение при возникновении ошибки. Потому что произошла ошибка, и она не должна быть скрыта.
Но в реальной жизни у вас может быть несколько ситуаций, когда вы хотите скрыть это
источник
Exception
. Когда-либо. Бросайте соответствующий подклассException
всего, что вы хотите, но никогда,Exception
потому что это не дает абсолютно никакой смысловой информации. Я совершенно не вижу сценария, в котором есть смысл бросать,Exception
но нет его подкласса.Вы должны рассмотреть эти Руководства по проектированию для Исключений
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/exceptions
источник
catch
Без каких - либо аргументов , просто едят исключение и бесполезно. Что если произойдет фатальная ошибка? Нет никакого способа узнать, что случилось, если вы используете catch без аргументов.Оператор catch должен перехватывать более конкретные исключения, например,
FileNotFoundException
а затем в самом конце вы должны перехватить,Exception
который перехватит любое другое исключение и зарегистрирует их.источник
catch(Exception)
в конце? Если вы этого не ожидаете, лучше всего передать его на следующий уровень.Иногда вам нужно обработать исключения, которые ничего не говорят пользователям.
Мой путь таков:
Это определенно не должно быть лучшей практикой. ;-)
источник
Я могу сказать вам кое-что:
Фрагмент # 1 недопустим, потому что он игнорирует исключение. (это глотает, как будто ничего не случилось).
Так что не добавляйте блок catch, который ничего не делает или просто отбрасывает.
Поймать блок должен добавить некоторую ценность. Например, вывод сообщения конечному пользователю или регистрация ошибок.
Не используйте исключения для нормальной логики программы потока. Например:
например, подтверждение ввода. <- Это недопустимая исключительная ситуация, скорее вы должны написать метод,
IsValid(myInput);
чтобы проверить, действителен ли элемент ввода или нет.Дизайн кода, чтобы избежать исключений. Например:
Если мы передадим значение, которое не может быть проанализировано, в int, этот метод вызовет исключение, вместо этого мы можем написать что-то вроде этого:
bool TryParse(string input,out int result);
<- этот метод возвращает логическое значение, указывающее, был ли анализ успешным.Возможно, это немного выходит за рамки этого вопроса, но я надеюсь, что это поможет вам принимать правильные решения, когда речь идет об
try {} catch(){}
исключениях.источник