Почему пустые блоки выгоды являются плохой идеей? [закрытый]

Я думаю, что это зависит от того, что Вы пытаетесь сделать за исключением.

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

Другой подход является подходом "повторной попытки", например, ошибочный подсчет проведен, и после определенного количества повторений это - единственное время, ошибка повышена стек (это иногда делается для доступа к базе данных для вызовов базы данных что тайм-аут, или в доступе к веб-сервисам по медленным сетям).

будет набор других причин сделать это все же.

176
задан Community 23 May 2017 в 11:47
поделиться

17 ответов

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

Это программный эквивалент наклеивания черной ленты сигнальной лампы двигателя.

Я считаю, что то, как вы справляетесь с исключениями, зависит от того, на каком уровне программного обеспечения вы работаете:

288
ответ дан 23 November 2019 в 20:22
поделиться
Я имею в виду, например, что иногда вы хотите получить дополнительную информацию откуда-то (веб-сервис, база данных), и вам действительно все равно, получите вы эту информацию или нет. Итак, вы пытаетесь получить это, и если что-то случится, ничего страшного, я просто добавлю «catch (Exception ignored) {}» и все

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

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

1
ответ дан 23 November 2019 в 20:22
поделиться

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

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}
1
ответ дан 23 November 2019 в 20:22
поделиться

Больше всего меня раздражают пустые операторы catch, когда это делал другой программист. Я имею в виду, что когда вам нужно отлаживать код от кого-то еще, любые пустые операторы catch делают такое мероприятие более трудным, чем должно быть. Операторы catch IMHO всегда должны показывать какое-то сообщение об ошибке - даже если ошибка не обрабатывается, она должна, по крайней мере, ее обнаруживать (только в режиме отладки)

1
ответ дан 23 November 2019 в 20:22
поделиться

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

1
ответ дан 23 November 2019 в 20:22
поделиться

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

Я могу вспомнить только несколько случаев, когда пустой блок catch имеет какое-то значимое назначение. Если какое-либо конкретное исключение, которое вы перехватываете, «обрабатывается» просто повторной попыткой действия, в блоке перехвата ничего делать не нужно. Тем не менее, было бы неплохо регистрировать факт возникновения исключения.

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

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

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

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

1
ответ дан 23 November 2019 в 20:22
поделиться

Пустой блок catch, по сути, говорит: «Я не хочу знать, какие ошибки возникают, я просто проигнорирую их»

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

Что не помогает, когда что-то затем выходит из строя.

3
ответ дан 23 November 2019 в 20:22
поделиться

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

1
ответ дан 23 November 2019 в 20:22
поделиться

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

Но даже в этом случае сообщение отладки может быть в порядке.

6
ответ дан 23 November 2019 в 20:22
поделиться

Исключения должны выдаваться только в том случае, если действительно существует исключение - что-то сверх нормы. Пустой блок catch в основном говорит, что «происходит что-то плохое, но мне все равно». Это плохая идея.

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

6
ответ дан 23 November 2019 в 20:22
поделиться

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

Кстати, большинство людей не знают, что за блоком try {} может следовать либо catch {} или finally {}, требуется только один.

6
ответ дан 23 November 2019 в 20:22
поделиться

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

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

35
ответ дан 23 November 2019 в 20:22
поделиться

Есть редкие случаи, когда это может быть оправдано. В Python вы часто видите такую ​​конструкцию:

try:
    result = foo()
except ValueError:
    result = None

Так что это может быть нормально (в зависимости от вашего приложения):

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

В недавнем проекте .NET мне пришлось написать код для перечисления подключаемых библиотек DLL, чтобы найти классы, которые реализовать определенный интерфейс. Соответствующий фрагмент кода (в VB.NET, извините):

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

Хотя даже в этом случае я бы признал, что регистрация сбоя где-нибудь, вероятно, была бы улучшением.

8
ответ дан 23 November 2019 в 20:22
поделиться

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

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

Например, рассмотрим некоторую библиотеку http-сервера, мне все равно, если сервер выдает исключение, потому что клиент отключился, и index.html не может быть отправлен.

10
ответ дан 23 November 2019 в 20:22
поделиться

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

3
ответ дан 23 November 2019 в 20:22
поделиться

Я считаю, что полностью пустой блок catch - плохая идея, потому что невозможно сделать вывод, что игнорирование исключения было предполагаемым поведением кода. Это не обязательно плохо, если проглотить исключение и в некоторых случаях вернуть false, null или другое значение. Фреймворк .net имеет множество методов «пробной», которые ведут себя подобным образом. Как правило, если вы проглотили исключение, добавьте комментарий и оператор журнала, если приложение поддерживает ведение журнала.

2
ответ дан 23 November 2019 в 20:22
поделиться

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

0
ответ дан 23 November 2019 в 20:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: