Почему бы не переносить каждый блок в & ldquo; try & rdquo; - & ldquo; catch & rdquo ;?

Что вы можете сделать (и я сделал), чтобы ссылка не работала, если человек, нажимая на нее, не использует Internet Explorer и открывает новое окно, обнаруживает DIV или всплывает alert(), сообщая им, что они должен использовать Internet Explorer для работы целевого сайта.

Что-то вроде:

some link

window.external.AddFavorite (насколько я знаю), доступный только в Internet Explorer, поэтому его использование для обнаружения IE должно быть достаточно безопасным. Вы также можете изучить navigator.userAgent для MSIE, однако некоторые браузеры, такие как Opera, могут обманывать пользовательский агент IE.

420
задан Raedwald 1 August 2018 в 12:13
поделиться

10 ответов

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

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

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

326
ответ дан Mitch Wheat 1 August 2018 в 12:13
поделиться

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

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

14
ответ дан Community 1 August 2018 в 12:13
поделиться

Как Митч и другие , вы не должны поймать исключение, которое вы не планируете обрабатывать каким-либо образом. Вы должны учитывать, как приложение будет систематически обрабатывать исключения при разработке. Это обычно приводит к тому, что уровни обработки ошибок основаны на абстракциях - например, вы обрабатываете все ошибки, связанные с SQL, в своем коде доступа к данным, так что часть приложения, взаимодействующая с объектами домена, не подвержена тому факту, что где-то есть БД под капотом.

Есть несколько связанных запахов кода, которые вы определенно хотите избежать, в дополнение к запаху «лови все везде» .

  1. «catch, log, rethrow» : если вы хотите вести журнал на основе границ, то напишите класс, который выдает оператор log в своем деструкторе, когда стек разворачивается из-за исключение (аля std::uncaught_exception()). Все, что вам нужно сделать, это объявить экземпляр журнала в интересующей вас области, и, вуаля, у вас есть протоколирование и нет ненужной логики try / catch.

  2. «поймай, брось переведено» : обычно это указывает на проблему абстракции. Если вы не внедряете федеративное решение, в котором вы переводите несколько конкретных исключений в одно более общее, вы, вероятно, имеете ненужный уровень абстракции ... и не говорите, что "оно может понадобиться мне завтра" .

  3. «поймать, очистить, отбросить» : это одна из моих любимых мозолей. Если вы видите многое из этого, вам следует применить методы «Приобретение ресурсов - инициализация» и поместить часть очистки в деструктор экземпляра объекта janitor . [ тысячу сто двадцать четыре]

Я считаю код, усеянный блоками try / catch, хорошей целью для проверки и рефакторинга кода. Это указывает на то, что либо обработка исключений не совсем понятна, либо код стал am'ba и нуждается в серьезном рефакторинге.

133
ответ дан Community 1 August 2018 в 12:13
поделиться

Мой профессор информатики однажды дал мне совет: «Используйте блоки Try and Catch только тогда, когда невозможно обработать ошибку стандартными средствами».

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

int f()
{
    // Do stuff

    if (condition == false)
        return -1;
    return 0;
}

int condition = f();

if (f != 0)
{
    // handle error
}

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

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

Херб Саттер писал об этой проблеме здесь . Обязательно стоит прочитать.
Тизер:

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

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

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

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

Поскольку следующий вопрос: «Я обнаружил исключение, что мне делать дальше?» Что ты будешь делать? Если ничего не делать - ошибка скрывается, и программа может «просто не работать» без возможности выяснить, что произошло. Вам нужно понимать, что именно вы будете делать после того, как поймаете исключение, и поймаете только в том случае, если знаете.

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

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

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

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

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

int ret = SaveFirstSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveSecondSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveThirdSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

Вот как это можно записать с исключениями:

// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();

Теперь стало намного яснее, что происходит.

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

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

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

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

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

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

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

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

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

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

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

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