Подтвердить что ты не робот

Все в порядке, что я иногда теряю свои исключения?

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

Если у вас есть метод чего-то НЕ-КРИТИЧЕСКОГО, что вы не хотите вмешиваться в важную работу вашего приложения, часто ли используется приемник ошибок?

Try 
    'do stuff.  not important if it fails.

Catch ex as exception
    'sink.  do nothing.
End Try

Если вы подумывали о найме меня, и вы читали мой код и видели это... не так ли?

Сет

ИЗМЕНИТЬ Вау! Спасибо за ваши ответы. Я думаю, что консенсус в том, что никогда не следует делать, или это должно быть очень редко.

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

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

Прилагаемая записка говорила: "Если это займет больше 15 минут... отбросьте ее".

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

Это было мое размышление. Но я принял ваше сообщение близко к сердцу... что в принципе это плохая идея.

Сет

4b9b3361

Ответ 1

Да, это обычное дело, но в целом это не должно быть сделано.

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

В большинстве случаев проглатывание System.Exception или System.SystemException неизбежно скрывает дальнейшие проблемы во время выполнения.

Ответ 2

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

Серьезно, однако, в Java (например) Исключения используются для определенных случаев, которые вы можете игнорировать, например FileNotFoundException (как и вы, с комментарием). Но если вы когда-нибудь поймаете тип Exception - например IOException - вы не можете просто скрыть его. Если Exception ничего не означает для вас, оберните его в RuntimeException и выбросьте его клиенту.

Где-то по пути, Exception следует обрабатывать, но никогда не скрывать.

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Я признаю: я проглотил исключения и в каждом случае это было потому, что ИМХО дизайнер функции прикручен.

"Исключения" означает "исключения", а не отказ или ошибка. Я имею в виду: если функция должен признать, что вход может быть неправильным, я ожидаю, что функция НЕ использовать исключения. Мой гнев нацелен, в частности, на "ParseException".

Если вы проанализируете ввод, вы, скорее всего, найдете неизвестный/поврежденный/неточный вход. Что является "нормальным", а не исключением. И в этом случае я нахожу это раздражающим, если разработчик функции выбрасывает ParseException, если функция не может правильно разобрать.

Почему?

  • Исключение прерывает поток управления
  • Исключение медленное
  • Часто это не имеет значения, потому что вы инициализируетесь со значениями по умолчанию.

Если вы вызываете parseFunction несколько тысяч или миллионы (!) раз, вы засоряете свой файл журнала ровно ничего.

Напротив, моя идеальная функция возвращает объект класса с кодом состояния и сообщение вроде

StatCode stat = parseXYZ(Reader r);

который затем может быть протестирован.

if (stat.code != OK)  
  //whatever

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

Ответ 6

Лучшие практики говорят, что вы не должны этого делать. Что не так важно, чтобы вы не хотели знать, что произошла ошибка? Я не думаю, что когда-либо сталкивался с этим.

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

Что моя мысль...

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

Ответ 7

Лично я вижу это как невероятно плохую практику.

Это (к сожалению) одна из вещей, которые я всегда искал при просмотре кода, и вопросы, которые я задаю, когда я нахожу пустые блоки catch или блоки catch, которые по существу проглатывают исключения:

  • На данный момент вы на 100% уверены, что это исключение не имеет значения?
  • Вы также на 100% уверены, что любое исключение, пойманное здесь в будущем, не имеет значения, независимо от того, как развивается база кода?
  • Даже если 1 и два являются истинными, действительно ли так сложно разместить некоторые записи здесь?

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

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

Ответ 8

Нет, это не ОК по-моему.

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

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

Ответ 10

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

try {
   Cache.refresh(myObject)
}
catch (NotInCacheException) {
   // If the object isn't already in the cache, then we don't have to worry 
   // about refreshing it. It assumed that this is a common occurrence,
   // so we don't need to log it either; that ends up just spamming
   // the logs. So, just swallow it, silently.
}

(Примечание. Независимо от того, должен ли Cache.refresh() вообще исключать исключение NotInCacheException, здесь я просто не говорю, я просто использую это как быстрый пример).

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

Кроме того: если у вас есть гибкая структура ведения журнала, вы можете в любое время регистрировать это исключение для информационных целей. Я думаю о Log4Net/Log4J, в частности, здесь: вы можете настроить ведение журнала (даже во время выполнения), чтобы выбрать/игнорировать исключения, основанные на классе и серьезности. Таким образом, вы можете отключить эти типы исключений при нормальных обстоятельствах, но зарегистрируйте их, если хотите сделать несколько попыток вашего приложения.

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

Ответ 11

Вы должны провести различие между игнорируемыми исключениями и фатальными исключениями. Я не уверен, как это делается в VB, но в Java (например) исключения, полученные из Error, никогда не должны игнорироваться. Это включает в себя такие вещи, как сбои загрузчика классов, условия отсутствия памяти, переполнение стека и т.д.

Ответ 12

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

Там какой-то код, если выбрасывает исключение, улавливает исключение, пытается что-то еще, и если это выдает исключение, делайте что-то еще и т.д. Исключения - это объекты и создаются при их броске. Если вы можете, напишите правильный код обработки, чтобы иметь дело с ошибкой, и используйте только исключения, если вы can't continue по какой-либо причине.

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

Ответ 13

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

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

Ответ 14

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

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

try {
 Integer.Parse(someString);
}
catch (ParseException pe) {
 //In this particular use case, if the string doesn't parse, 
 //I don't need to do anything. Logging a warning might be a
 //good idea, in some cases
}

Вы делаете код очистки безопасным:

beginDatabaseTransaction();
try {
 doSomeDatabaseOperation();
}
catch (Exception e) {
 log.error(e); //log the original exception
 try {
  rollbackDatabaseConnection();
 }
 catch(Exception e2) {
  //You may ignore this one-off exception, though
  //I would strongly consider logging it
 }
 throw; //rethrow the original exception and let it propagate
}

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

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

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

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

Ответ 15

В общем, я бы сказал, что это плохая практика, но скажем, что этот метод является методом ведения журнала. Я не хочу, чтобы мое приложение разбилось, потому что EventLog заполнен. В таком случае, я бы сказал, все в порядке. Я все равно вывел его в окно Debug.

Ответ 16

Я бы сказал: "Не делай этого" - не так.

Прежде всего, попробуйте рефакторинг "некритического" кода, чтобы он не генерировал исключение.

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

Ответ 17

.if с помощью vs2008 вы могли бы по крайней мере отправить их в окно отладки

 System.Diagnostics.Debug.WriteLine("exception in method - my method -: "+ex.message);

Ответ 18

Я делаю это только при раздражающих упражнениях, таких как закрытие соединения:

try {
   conn.close()
}
catch( Exception e ) {
}

потому что я уже уверен, что мне это больше не нужно.

Ответ 19

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

Ответ 20

Если это хорошо или нет, зависит от языка и того, насколько дорогими исключениями. Вы по-прежнему не должны ломать ВСЕ исключения, но, например, в Python следующая общая идиома:

d={}
for i in theList:
  try:
    d[i] += 1
  except KeyError:
    d[1] = 1

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

Ответ 21

Java выдвинула на первый план необходимость программирования с помощью Exceptions. Я обнаружил, что Java склонен охотно бросать Исключения, что раздражает, потому что вы должны их поймать, если вы не хотите, чтобы ваше приложение разбилось. К сожалению, Исключения в Java - довольно тяжелая функция.

Я узнал об эффективном использовании исключений в Icon. Икона имеет эту опрятную вещь под названием "Отказ". Если выражение не имеет значения, которое оно может вернуть, оно будет вместо Fail. Это работает как миниатюрное исключение, вместо обозначения try {} catch {}, Failure обрабатывается непосредственно языковыми элементами, такими как if и while.

ИМО, вот как Исключения должны работать на Java... но, к сожалению, они этого не делают. Вместо этого вы в конечном итоге пишете защитный код, чтобы исключить исключения, а не обрабатывать их легко и естественно. Безмолвно проглатывая особое исключение, потому что оно достаточно редко и намного более элегантно, чем предотвращает его, я бы рассматривал как Полезный трюк. Но это то, что отвечает на "Вы должны знать правила, прежде чем сможете их разбить". Другими словами, не делайте этого слишком часто.

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