Это нормально, что я иногда опускаю свои исключения? - PullRequest
36 голосов
/ 26 января 2010

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

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

Try 
    'do stuff.  not important if it fails.

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

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

Сет

EDIT Вот Это Да! Спасибо за ваши ответы. Я думаю, что консенсус заключается в том, что никогда не должно быть сделано, или это должно быть очень редко.

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

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

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

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

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

Сет

Ответы [ 21 ]

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

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

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

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

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

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's 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, что на way слишком высокий уровень (вы будете глотать критические ошибки, как уже упоминали другие).

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

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

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

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

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

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.) Когда вы перехватываете неизвестное исключение, вы скрываете ошибку от своего работающего в данный момент кода и позволяете коду работать неожиданно, а не просто завершаться.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...