Есть ли веская причина игнорировать исключение

Ничего себе, я только что вернул огромный проект на С# от сторонних разработчиков, и, просматривая мой обзор кода, мой инструмент анализа обнаружил пучки того, что он считал плохим. Одним из наиболее неприятных сообщений было:

Exceptions.DontSwallowErrorsCatchingNonspecificExceptionsRule  : 2106 defects 

Разработчики уверяют меня, что у них есть веская причина для всех пустых блоков catch, которые иногда пытаются с пустыми блоками catch, чтобы игнорировать бесполезные исключения и не допустить сбой приложения. Я чувствую, что это полицейский и полный BS. Некоторые из примеров, которые я действительно искал, были вызовами базы данных, где запись была сохранена в базе данных, и в этом случае, если исключение было проигнорировано, пользователь вернул бы подсказку, считая, что все в порядке, и продолжайте их работа. На самом деле их работа никогда не спасалась. Я думаю, что это абсолютно ужасная ошибка. В этом случае они совершенно ошибочны, бросая этот код в попытке с пустым блоком catch. Но мой вопрос: "Является ли это КАЖДОЕ приемлемым в ЛЮБОЙ ситуации?" Я думаю, что нет, но я, как известно, ошибался.

Ответ 1

Хотя есть некоторые разумные причины для игнорирования исключений; однако, как правило, это только конкретные исключения, которые вы можете безопасно игнорировать. Как отметил Конрад Рудольф, вам, возможно, придется поймать и усвоить ошибку как часть структуры; и, как отмечено osp70, может возникнуть исключение, генерируемое каркасом, который, как вы знаете, можно игнорировать.

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

try {
  // Do something that might generate an exception
} catch (System.InvalidCastException ex) {
  // This exception is safe to ignore due to...
} catch (System.Exception ex) {
  // Exception handling
}

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

Ответ 2

Я не поймаю исключения, если я не собираюсь что-то делать с ними. Игнорирование их не делает ничего о них.

Ответ 3

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

Однако я регистрирую ошибку. Я просто не реконструирую его.

Ответ 4

Я чувствую, что любой пустой Catch Block нуждается в комментарии.

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

Кроме того, вы не захотите сделать его общим "catch (Exception e) {}".

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

Ответ 5

Обычно нет, на самом деле нет в 99% всех случаев, НО

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

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

Ответ 6

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

public void testSomething(){
    try{
        fooThatThrowsAnException(parameterThatCausesTheException);
        fail("The method didn't throw the exception that we expected it to");
    } catch(SomeException e){
        // do nothing, as we would expect this to happen, if the code works OK.
    }
}

Обратите внимание, что, хотя блок catch ничего не делает, он объясняет, почему.

Сказав это, более свежие рамки тестирования (Junit4 и TestNG) позволяют вам указать ожидаемое исключение - что приводит к чему-то вроде этого...

@Test(expected = SomeException.class)
public void testSomething(){
    fooThatThrowsAnException(parameterThatCausesTheException);
    fail("The method didn't throw the exception that we expected it to");
}

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

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

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

Ответ 10

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

Ответ 11

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

    public FileStream OpenFile(string path)
    {
        FileStream f = null;
        try
        {
            f = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
        }
        catch (FileNotFoundException)
        {
        }
        return f;
    }

Вы также можете написать метод следующим образом:

    public FileStream OpenFile(string path)
    {
        FileStream f = null;
        FileInfo fi = new FileInfo(path);
        if (fi.Exists)
        {
            f = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);                
        }
        return f;
    }

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

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

Но это игнорирует конкретное исключение. Этот код:

catch
{
}

непростительно.

Нет никакой веской причины не поймать конкретное типизированное исключение, которое код в блоке try собирается выбросить. Первая причина, по которой наивный разработчик дает для исключения исключений, независимо от типа: "Но я не знаю, какой тип исключения может быть брошен", - это своего рода ответ на вопрос.

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

Ответ 12

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

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

Ответ 13

Когда дело доходит до Исключения, всегда есть исключения.

Ответ 14

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

Ответ 15

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

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

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

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

Ответ 16

Мне очень интересно об этом конкретном.

Connection con = DriverManager.getConnection(url, "***", "***");

try {
    PreparedStatement pStmt = con.prepareStatement("your query here");

    ... // query the database and get the results
}
catch(ClassNotFoundException cnfe) {
    // real exception handling goes here
}
catch(SQLException sqle) {
    // real exception handling goes here
}
finally {
    try {
        con.close();
    }
    catch {
        // What do you do here?
    }
}

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

Ответ 17

Если ваш код catch не будет

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

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

Ответ 18

Чтобы взять пример из мира Java, где он ОК, чтобы игнорировать исключение:

String foo="foobar";
byte[] foobytes;

try
{
    foobytes=foo.getBytes("UTF-8");
}
catch (UnsupportedEncodingException uee)
{
    // This is guaranteed by the Java Language Specification not to occur, 
    // since every Java implementation is required to support UTF-8.
}

Тем не менее, даже в таких ситуациях я часто использую

...
catch (UnsupportedEncodingException uee)
{
    // This is guaranteed by the Java Language Specification not to occur, 
    // since every Java implementation is required to support UTF-8.
    uee.printStackTrace();
}

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

Ответ 19

Это очень плохо, что нужно делать.

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

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

Ответ 20

Следующие слова применяются только к языкам, которые проверяют исключения, например. Java:

Иногда метод выдает проверенное исключение, которое, как вы знаете, не произойдет, например. некоторые API-интерфейсы Java ожидают имя кодировки в виде строки и выдают исключение UnsupportedEncodingException, если данная кодировка не поддерживается. Но обычно я передаю литерал "UTF-8", который, как я знаю, поддерживается, поэтому я мог теоретически написать пустую запись.

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

Ответ 21

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

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

Ответ 22

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

Ответ 23

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

Ответ 24

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

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