Как зайти в Даркнет?!
25th January, 01:11
94
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
1228
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
1029
0
Очень долго работает Update запрос Oracle
27th January, 09:58
969
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
959
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
995
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1782
0
период по дням
25th October, 10:44
4001
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3775
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4661
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4442
0
Помогите пожалуйста решить задачи
24th November, 23:53
6159
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4393
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4442
0
Метода Крамера С++
23rd October, 11:55
4356
0
помогите решить задачу на C++
22nd October, 17:31
4040
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4533
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2643
0
Неужели так уж плохо поймать общее исключение?
Анализируя некоторый устаревший код с FXCop, мне пришло в голову, действительно ли так плохо поймать общую ошибку исключения в блоке try или вы должны искать конкретное исключение. Мысли на открытке, пожалуйста.
Очевидно, это один из тех вопросов, где единственный реальный ответ-"it depends."
Главное, что это зависит от того, где вы ловите исключение. В общем случае библиотеки должны быть более консервативны с перехватом исключений, тогда как на верхнем уровне вашей программы (например, в вашем основном методе или в верхней части метода действия в контроллере и т. д.) Вы можете быть более либеральны с тем, что вы ловите.
Причина этого заключается в том, что напр. вы не хотите ловить все исключения в библиотеке, потому что вы можете замаскировать проблемы, которые не имеют ничего общего с вашей библиотекой, например "OutOfMemoryException", которые вы действительно предпочли бы всплывать, чтобы пользователь мог получать уведомления и т. д. С другой стороны, если вы говорите о ловле исключений внутри вашего метода main(), который ловит исключение, отображает его и затем завершает работу... Ну, здесь, наверное, можно спокойно поймать практически любое исключение.
Самое важное правило о ловле всех исключений состоит в том, что вы никогда не должны просто молча проглатывать все исключения... например, что-то вроде этого в Java:
try {
something();
} catch (Exception ex) {}
или это в Python году:
try:
something()
except:
pass
Потому что это может быть одним из самых сложных вопросов для отслеживания.
Хорошее эмпирическое правило состоит в том, что вы должны ловить только те исключения, с которыми вы можете правильно справиться сами. Если вы не можете справиться с исключением полностью, то вы должны позволить ему всплыть до того, кто может.
Если вы не делаете некоторые записи в журнал и не очищаете код в переднем конце вашего приложения, то я думаю, что это плохо, чтобы поймать все исключения.
Мое основное эмпирическое правило-ловить все исключения, которые вы ожидаете, а все остальное-ошибка.
Если вы поймаете все и продолжите движение, это немного похоже на то, как если бы вы наклеили пластырь на предупредительную лампочку на приборной панели вашего автомобиля. Вы больше не можете его видеть, но это не значит, что все в порядке.
Да! (за исключением "top" вашего заявления)
Перехватив исключение и позволив продолжить выполнение кода, Вы заявляете, что знаете, как справиться с конкретной проблемой, обойти ее или устранить. Вы утверждаете, что это вполне поправимая ситуация . Перехват исключения или SystemException означает, что вы будете ловить такие проблемы, как IO ошибок, сетевые ошибки, out-of-memory ошибок, Ошибки пропущенного кода, null-pointer-dereferencing и тому подобные. Это ложь-говорить, что вы можете справиться с ними.
В хорошо организованном приложении эти неустранимые проблемы должны решаться высоко в стеке.
Кроме того, по мере развития кода Вы не хотите, чтобы ваша функция перехватывала новое исключение, которое будет добавлено в будущем к вызываемому методу.
На мой взгляд, вы должны ловить все исключения, которые вы ожидаете, но это правило применимо ко всему, кроме вашей логики интерфейса. На всем пути вниз по стеку вызовов вы, вероятно, должны создать способ поймать все исключения, сделать некоторые записи в журнал/дать отзыв пользователя и, если это необходимо и возможно, изящно завершить работу.
Нет ничего хуже, чем сбой приложения с каким-то недружественным пользователем stacktrace, сброшенным на экран. Это не только дает (возможно, нежелательное) представление о вашем коде, но и сбивает с толку конечного пользователя, а иногда даже отпугивает его от конкурирующего приложения.
Ну, я не вижу никакой разницы между ловлей общего исключения или конкретного, за исключением того, что при наличии нескольких блоков catch вы можете реагировать по-разному в зависимости от того, что такое исключение.
В заключение, вы поймаете оба IOException и NullPointerException с общим Exception, но то, как ваша программа должна реагировать, вероятно, отличается.
Я думаю, дело тут в двух вещах.
Во-первых, если вы не знаете, какое исключение произошло, как вы можете надеяться на восстановление после него. Если вы ожидаете, что пользователь может ввести имя файла неправильно, то вы можете ожидать FileNotFoundException и попросить пользователя повторить попытку. Если тот же самый код сгенерировал NullReferenceException, и вы просто сказали пользователю попробовать еще раз, они не будут знать, что произошло.
Во-вторых, руководящие принципы FxCop действительно сосредоточены на библиотечном / рамочном коде - не все их правила предназначены для применения к веб-сайтам EXE или ASP.Net. Поэтому наличие глобального обработчика исключений, который будет регистрировать все исключения и красиво выходить из приложения, - это хорошая вещь.
Проблема с перехватом всех исключений заключается в том, что вы можете ловить те, которые вы не ожидаете, или действительно те, которые вы не должны ловить. Дело в том, что любое исключение указывает на то, что что-то пошло не так, и вы должны разобраться в этом, прежде чем продолжить, иначе вы можете столкнуться с проблемами целостности данных и другими ошибками, которые не так легко отследить.
Чтобы привести один пример, в одном проекте я реализовал тип исключения с именем CriticalException. Это указывает на состояние ошибки, которое требует вмешательства разработчиков и / или административного персонала, иначе клиенты получают неверный счет или могут возникнуть другие проблемы с целостностью данных. Он также может быть использован в других подобных случаях, когда просто регистрировать исключение недостаточно, и необходимо отправить предупреждение по электронной почте.
Другой разработчик, который не совсем понимал концепцию исключений, затем завернул некоторый код, который потенциально мог бы бросить это исключение в общий блок try...catch, который отбрасывал все исключения. К счастью, я заметил его, но это могло привести к серьезным проблемам, особенно с учетом того, что случай с углом "very uncommon", который он должен был поймать, оказался гораздо более распространенным, чем я ожидал.
Таким образом, в целом, перехват общих исключений является плохим, если вы не уверены 100%, что точно знаете, какие виды исключений будут выброшены и при каких обстоятельствах. Если вы сомневаетесь, пусть они всплывают до обработчика исключений верхнего уровня вместо этого.
Аналогичное правило здесь-никогда не выбрасывать исключения типа System.Exception. Вы (или другой разработчик) можете захотеть перехватить ваше конкретное исключение выше по стеку вызовов, позволяя другим проходить через него.
(Однако следует отметить один момент. В .NET 2.0, если поток обнаруживает какие-либо необработанные исключения, он выгружает весь домен приложения. Таким образом, вы должны обернуть основное тело потока в универсальный блок try...catch и передать любые исключения, пойманные там, в ваш глобальный код обработки исключений.)
Я бы хотел сыграть роль адвоката дьявола для того, чтобы поймать исключение, записать его и переосмыслить. Это может быть необходимо, если, например, вы находитесь где-то в коде и происходит непредвиденное исключение, вы можете поймать его, записать значимую информацию о состоянии, которая не была бы доступна в простом стеке trace, а затем перестроить ее на верхние слои для работы.
Есть два совершенно разных варианта использования. Первый - это тот, о котором думает большинство людей, ставя try/catch вокруг некоторой операции, которая требует проверенного исключения. Это ни в коем случае не должно быть подвохом.
Второй, однако, заключается в том, чтобы остановить вашу программу от разрыва, когда она может продолжить работу. Эти случаи являются:
- Верхняя часть всех потоков (по умолчанию исключения будут исчезать без trace!)
- Внутри основного цикла обработки, который вы ожидаете никогда не выйти
- Внутри цикла обработки списка объектов, где один сбой не должен останавливать другие
- В верхней части потока "main"-вы можете управлять сбоем здесь, например, сбрасывать немного данных в stdout, когда у вас заканчивается память.
- Если у вас есть "Runner", который выполняет код (например, если кто-то добавляет прослушиватель к вам, и вы вызываете прослушиватель), то при запуске кода Вы должны поймать исключение, чтобы зарегистрировать проблему и позволить вам продолжать уведомлять других слушателей.
В этих случаях вы ALWAYS хотите поймать исключение (возможно, даже иногда бросаемое), чтобы поймать Программирование / неожиданные ошибки, зарегистрировать их и продолжить.
Я думаю, что хорошим руководством является перехват только определенных исключений из фреймворка (чтобы ведущее приложение могло иметь дело с крайними случаями, такими как заполнение диска и т. д.), Но я не вижу, почему мы не должны быть в состоянии перехват всех исключений из нашего кода приложения. Просто есть моменты, когда вы не хотите, чтобы приложение рухнуло, независимо от того, что может пойти не так.
Улавливая общее исключение, я чувствую себя так, словно держу динамитную шашку внутри горящего здания и тушу взрыватель. Это помогает на короткое время, но динамит все равно взорвется через некоторое время.
В corse могут возникнуть ситуации, когда перехват общего исключения необходим, но только для целей отладки. Ошибки и баги должны быть исправлены, а не скрыты.
Для моего класса IabManager, который я использовал с биллингом в приложении (из примера TrivialDrive онлайн), я заметил, что иногда я имел дело с большим количеством исключений. Дело дошло до того, что оно стало непредсказуемым.
Я понял, что, если я прекращу попытки использовать продукт в приложении после того, как произойдет одно исключение, а именно там произойдет большинство исключений (в consume, а не в buy), я буду в безопасности.
Я просто изменил все исключения на общее исключение, и теперь мне не нужно беспокоиться о каких-либо других случайных, непредсказуемых исключениях.
До:
catch (final RemoteException exc)
{
exc.printStackTrace();
}
catch (final IntentSender.SendIntentException exc)
{
exc.printStackTrace();
}
catch (final IabHelper.IabAsyncInProgressException exc)
{
exc.printStackTrace();
}
catch (final NullPointerException exc)
{
exc.printStackTrace();
}
catch (final IllegalStateException exc)
{
exc.printStackTrace();
}
После:
catch (final Exception exc)
{
exc.printStackTrace();
}
Непопулярное мнение: не совсем так.
Ловите все ошибки, которые вы можете осмысленно исправить. Иногда это все они.
По моему опыту, гораздо важнее, откуда взялось исключение, а не то, какое исключение на самом деле выбрасывается. Если вы держите свои исключения в узком кругу, вы обычно не будете глотать ничего, что в противном случае было бы полезно. Большая часть информации, закодированной в типе ошибки, является вспомогательной информацией, поэтому вы обычно эффективно ловите все их в любом случае (но теперь вам нужно посмотреть документы API, чтобы получить полный набор возможных исключений).
Имейте в виду, что некоторые исключения, которые должны всплывать наверх почти в каждом случае, такие как Python KeyboardInterrupt и SystemExit . К счастью для Python, они хранятся в отдельной ветви иерархии исключений, поэтому вы можете позволить им всплывать, поймав Exception . Хорошо продуманная иерархия исключений делает этот тип вещей действительно простым.
Основное время, когда перехват общих исключений вызовет серьезные проблемы, - это когда речь идет о ресурсах, которые необходимо очистить (возможно, в предложении finally ), так как обработчик catch-all может легко пропустить такие вещи. К счастью, это не совсем проблема для языков с defer, конструкциями типа Python в with или RAII в C++ и Rust.