Где вы любите ловить исключения и почему?

Где вы любите ловить исключения и почему?

Мне интересно узнать, где люди считают полезным размещать свои блоки try / catch в надежде, что могут появиться какие-то общие закономерности. Я отправлю свои два примера ответов на C ++, но любой язык подойдет.

Одно место и причина для каждого ответа, пожалуйста. Спасибо.


person Community    schedule 12.01.2009    source источник
comment
Опрос определенно должен быть вики, если вы предоставляете варианты!   -  person Greg    schedule 12.01.2009


Ответы (9)


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

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

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

РЕДАКТИРОВАТЬ: Если вам нужен блок finally (например, чтобы выпустить что-то, что вы выделили в своем коде), и вам нечего делать с любыми исключениями, которые могут появиться, применяется та же логика: просто не обрабатывайте их. Вместо этого используйте catch { throw; }, чтобы перебросить исключение на более высокий уровень, сохранив при этом всю информацию об исключении. (Или просто опустите блок catch, который, как я думаю / надеюсь, делает то же самое?)

person peSHIr    schedule 12.01.2009
comment
О, это на C #, если вы не заметили. (То же самое и с другими языками .NET.) - person peSHIr; 12.01.2009

Я стараюсь ловить ТОЛЬКО те исключения, с которыми могу справиться.

Я НЕНАВИЖУ такой код:

      String s="12";
      Integer i;
        try {
          i = Integer.parseInt(s);
        } catch(ParseException pe) {
          System.out.println("hihihihihihihi!!!);
        }

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

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

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

catch(Exception e) {
  throw new RuntimeException(e);
}

И я объявляю много «бросков» в своих определениях функций.

Я все еще мечтаю о том дне, когда Eclipse автоматически откроет отладчик в правильной строке, когда получит неперехваченное исключение. В этот день мой метод откроет правильную строку.

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

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

person nes1983    schedule 12.01.2009
comment
Привет, nes1983 Не уверен, что вы знаете о http://stackoverflow.com/questions/3066199/eclipse-break-when-exception-is-thrown - по поводу вашего комментария о том дне, когда Eclipse автоматически откроет для вас отладчик. Это не совсем то, что вы ищете, но поможет ли вам добраться туда? Оценил ваш ответ между прочим. - person GrahamMc; 19.01.2011

Я всегда помещаю уловку в main () как крайнюю уловку:

int main( int argc, char** argv ) {
    try {
        Application application( argc, argv );
        return application.result();
    }
    catch ( const std::exception& exception ) {
        fprintf( stderr, "%s.\n", exception.what() );
    }
}
person Community    schedule 12.01.2009

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

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

person krosenvold    schedule 12.01.2009

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

public void stuff() throws MyException
{
    try
    {
        tryStuff();
    }
    catch (SomeLibraryException e)
    {
        logger.log("Some message happened", e);
        throw new MyException(e);
    }
}

public void tryStuff() throws SomeLibraryException
{
   // Do things in here that could throw exceptions
}
person willcodejavaforfood    schedule 12.01.2009

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

void Controller::on_edit_entity( const Entity& entity ) {
    try {
        Command::ptr command = new EditEntityCommand( entity );
        push_command( command );
    }
    catch ( const std::exception& exception ) {
        fprintf( stderr, "%s.\n", exception.what() );
    }
}
person Community    schedule 12.01.2009
comment
Не заставляйте пользователя понять это. Если вы не можете обработать исключение - исправить любую проблему, вызвавшую его в первую очередь, - тогда не ловите его, чтобы в дальнейшем код не упал, потому что он предполагает, что все в порядке, хотя на самом деле это не так. Например, ваш код перехватывает std :: bad_alloc. - person Rob Kennedy; 12.01.2009

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

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

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

  • Мне нужно выполнить некоторую очистку (например, откат БД), и в этом случае я бы повторно вызвал исключение после завершения очистки.
  • У меня есть дополнительная информация, которую я могу добавить к этому исключению.
  • Несмотря на исключение, мой метод может преуспеть в достижении поставленной цели.
person CodeAndCats    schedule 12.01.2009

(Прежде чем я начну: я парень Java)
Что я рекомендую:

  1. Найдите ближайшую точку в цепочке вызовов от источника исключения, где вы можете обработать исключение должным образом - например, принять меры по исправлению, сбой сигнала транзакции / действия и т. Д. (Ведение журнала само по себе не должно рассматриваться как обработка исключений) Все методы между обработчиком и метателем следует игнорировать исключение. Предпочитайте непроверенные исключения отмеченным, чтобы исключения даже не фигурировали во всех этих промежуточных методах.
  2. Границы уровня и API-интерфейсы должны указывать исключения, которые он может генерировать с помощью проверенных исключений, поскольку обработка этих исключений является частью контракта для клиентского уровня / кода, который его использует.
  3. Напишите класс обработчика исключений с handle(Exception e) методом и сначала передайте его команде, а также убедитесь, что все используют его для обработки исключений. Основываясь на изменении сценариев обработки исключений, продолжайте добавлять перегруженные методы «дескриптора» позже, так что нужно будет изменять только обработчик.
  4. Всегда не забывайте связывать исключения в цепочке при выполнении ловли и бросания. Это гарантирует, что будет сообщена полная причина исключения.
  5. Никогда не записывайте одну и ту же трассировку исключения более одного раза. Это затрудняет отладку с использованием файлов журнала.
  6. Методы верхнего уровня должны иметь предложение catch, которое будет перехватывать любое исключение, которое может создать система. Это предотвращает утечку нашей внутренней информации во внешний мир, если, не дай бог, что-то пойдет не так в производственной среде. Это скорее требование безопасности.
person rahulmohan    schedule 23.06.2011

Два места:

  • Во всех обработчиках событий
  • Любое место, где уловка может сделать что-то полезное, например, дополнить исключение информацией, которая будет полезна для отладки. Обычно с этой информацией создается и выбрасывается новое исключение. Обратите внимание, что для InnerException (или эквивалента, отличного от .NET) этого нового исключения должно быть установлено значение исходного исключения, чтобы такие вещи, как трассировка стека, были сохранены.
person Richard Ev    schedule 12.01.2009