Почему бы мне не обернуть каждый блок в «try» - «catch»? - PullRequest
418 голосов
/ 29 апреля 2010

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

Я только что опубликовал ' Вы должны ВСЕГДА оборачивать вызовы, которые могут вызывать попытки, перехватывать блоки. хотелось бы понять почему.

Ответы [ 16 ]

2 голосов
/ 16 февраля 2012

Если вы хотите проверить результат каждой функции, используйте коды возврата.

Цель исключений состоит в том, чтобы вы могли часто проверять результаты МЕНЬШЕ. Идея состоит в том, чтобы отделить исключительные (необычные, более редкие) условия от вашего более обычного кода. Это делает обычный код чище и проще - но все же способен справляться с этими исключительными условиями.

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

1 голос
/ 03 декабря 2017

Я хотел бы добавить к этому обсуждению, что , начиная с C ++ 11 , имеет большой смысл, если каждый catch блок rethrow является исключением вплоть до указать, что это может / должно быть обработано. Таким образом, можно сгенерировать обратную трассировку . Поэтому я считаю, что предыдущие мнения частично устарели.

Используйте std::nested_exception и std::throw_with_nested

В StackOverflow здесь и здесь описано, как этого добиться.

Поскольку вы можете сделать это с любым производным классом исключений, вы можете добавить много информации к такой обратной трассировке! Вы также можете взглянуть на мой MWE на GitHub , где обратная трассировка будет выглядеть примерно так:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
1 голос
/ 11 апреля 2012

Помимо вышеприведенного совета, лично я использую несколько команд try + catch + throw; по следующей причине:

  1. На границе другого кодера я использую try + catch + throw в коде, написанном мной самостоятельно, перед тем, как исключение выдается вызывающей программе, которое пишется другими, это дает мне возможность узнать, какое состояние ошибки возникло в моем код, и это место гораздо ближе к коду, который изначально выдает исключение, чем ближе, тем легче найти причину.
  2. На границе модулей, хотя разные модули могут быть написаны одним и тем же человеком.
  3. Цель обучения + отладки, в этом случае я использую catch (...) в C ++ и catch (Exception ex) в C #, для C ++ стандартная библиотека не выдает слишком много исключений, поэтому этот случай редок в C ++ , Но общее место в C #, C # имеет огромную библиотеку и развитую иерархию исключений, код библиотеки C # генерирует тонны исключений, в теории я (и вы) должны знать все исключения из вызванной вами функции и знать причину / случай, почему эти исключения выдают, и знают, как с ними справиться (пройти мимо или поймать и обработать его на месте) изящно. К сожалению, на самом деле очень сложно узнать все о потенциальных исключениях, прежде чем я напишу одну строку кода. Поэтому я ловлю все и позволяю своему коду говорить вслух, регистрируя (в среде продукта) / диалог подтверждения (в среде разработки), когда действительно происходит какое-либо исключение. Таким образом, я постепенно добавляю код обработки исключений. Я знаю, что это совпало с хорошим советом, но на самом деле это работает для меня, и я не знаю лучшего способа решения этой проблемы.
0 голосов
/ 07 марта 2019

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

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

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

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

Короче говоря, try / catches усложняет понимание кода.

0 голосов
/ 09 августа 2017

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

Как моя команда исправила проблемы без значительного изменения пользовательского интерфейса? Все просто, каждый метод был снабжен блокировкой try..catch, и все было зарегистрировано в точке сбоя с именем метода, значения параметров метода объединены в строку, переданную вместе с сообщением об ошибке, сообщением об ошибке, именем приложения, датой, и версия. С помощью этой информации разработчики могут запускать аналитику на наличие ошибок, чтобы выявить исключение, которое возникает чаще всего! Или пространство имен с наибольшим количеством ошибок. Он также может подтвердить, что ошибка, возникающая в модуле, правильно обрабатывается и не вызвана несколькими причинами.

Еще одно преимущество этого преимущества заключается в том, что разработчики могут установить одну точку останова в методе регистрации ошибок, и с одной точкой останова и одним щелчком мыши по кнопке отладки «выйти» они находятся в методе, который не удался с полным доступом для реальных объектов в точке отказа, удобно доступны в непосредственном окне. Это делает его очень простым для отладки и позволяет перетаскивать выполнение назад в начало метода, чтобы дублировать проблему, чтобы найти точную строку. Позволяет ли централизованная обработка исключений разработчику воспроизвести исключение за 30 секунд? №

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

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

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

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

Этот метод использовался для быстрой стабилизации приложения, которое каждый час давало сбой большинству пользователей в компании из списка Fortune 500, разработанной 12 разработчиками в течение 2 лет. Используя эти 3000 различных исключений, были выявлены, исправлены, протестированы и развернуты в течение 4 месяцев. Это в среднем исправляет каждые 15 минут в среднем в течение 4 месяцев.

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

0 голосов
/ 15 декабря 2015

Вам не нужно скрывать каждую часть кода внутри try-catch. Основное использование блока try-catch - обработка ошибок и ошибок / исключений в вашей программе. Некоторое использование try-catch -

  1. Вы можете использовать этот блок там, где хотите обработать исключение, или просто можете сказать, что блок письменного кода может вызвать исключение.
  2. Если вы хотите утилизировать свои объекты сразу после их использования, вы можете использовать try-catch block.
...