Лучшие практики управления исключениями на Java или C #

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

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

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

Вот пример кода (на JAVA) типичного метода)

public boolean doSomething(Object p_somthingToDoOn)
{
    boolean result = false;

    try{
        // if dirty object then clean
        doactualStuffOnObject(p_jsonObject);

        //assume success (no exception thrown)
        result = true;
    }
    catch(Exception Ex)
    {
        //don't care about exceptions
        Ex.printStackTrace();
    }
    return result;
}

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

Резюме основных вопросов:

  1. Можно ли просто перехватить исключения, но не всплывать или формально уведомлять систему (либо через журнал, либо через уведомление для пользователя)?
  2. Какие существуют передовые практики для исключений, которые не приводят ко всему, что требует блока try / catch?

Последующие действия / редактирование

Спасибо за все отзывы, нашел несколько отличных источников по управлению исключениями в Интернете:

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

Кроме того, следите за гниением кода из-за чрезмерного количества попыток / уловок или отказа от исключения (исключение - предупреждение системы, о чем еще нужно предупредить?).

Кроме того, это прекрасный комментарий от m3rLinEz.

Я склонен согласиться с Андерсом Хейлсбергом и вами в том, что большинство звонящих заботятся только о том, прошла ли операция успешно или нет.

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

  • В чем смысл этого исключения?
  • Как имеет смысл с этим справляться?
  • Действительно ли вызывающий абонент заботится об исключении или его просто волнует, был ли вызов успешным?
  • Является ли изящным принуждение вызывающего абонента к управлению потенциальным исключением?
  • Are you being respectful to the idoms of the language?
    • Do you really need to return a success flag like boolean? Returning boolean (or an int) is more of a C mindset than a Java (in Java you would just handle the exception) one.
    • Следуйте конструкциям управления ошибками, связанным с языком :)!

person Community    schedule 03.01.2009    source источник
comment
Хотя статья сообщества оракулов написана на java, это общий совет для очень широкого класса языков. Хорошая статья, именно то, что я искал.   -  person Bunny Rabbit    schedule 20.10.2016


Ответы (15)


Мне кажется странным, что вы хотите перехватывать исключения и превращать их в коды ошибок. Как вы думаете, почему вызывающий абонент предпочел бы коды ошибок исключениям, если последнее является значением по умолчанию как в Java, так и в C #?

Что касается ваших вопросов:

  1. Вы должны перехватывать только те исключения, с которыми действительно можете справиться. В большинстве случаев просто перехватить исключения - не лучший вариант. Есть несколько исключений (например, журналирование и маршаллинг исключений между потоками), но даже в этих случаях вам обычно следует повторно генерировать исключения.
  2. У вас определенно не должно быть много операторов try / catch в вашем коде. Опять же, идея состоит в том, чтобы перехватывать только те исключения, которые вы можете обработать. Вы можете включить обработчик исключений верхнего уровня, чтобы превратить любые необработанные исключения во что-то полезное для конечного пользователя, но в противном случае вам не следует пытаться перехватывать каждое исключение во всех возможных местах.
person Brian Rasmussen    schedule 03.01.2009
comment
Что касается того, почему кому-то нужны коды ошибок вместо исключений ... Мне всегда казалось странным, что HTTP по-прежнему использует коды ошибок, хотя мое приложение генерирует исключение. Почему HTTP не может позволить мне передать исключение как есть? - person Trejkaz; 24.08.2012
comment
Лучшее, что вы можете сделать, это обернуть свои коды ошибок в монаду - person lindenrovio; 06.02.2014
comment
@Trejkaz Вы не хотите возвращать подробности исключения пользователям, потому что это угроза безопасности. Вот почему серверы HTML возвращают коды ошибок. Возврат сообщения об ошибке также связан с проблемой локализации, что, вероятно, приводит к увеличению размера HTML и замедлению возврата. Вот почему я думаю, что HTML-серверы возвращают коды ошибок. - person Didier A.; 01.11.2014
comment
Я думаю, лучше сказать: вы должны подавлять только те исключения, с которыми вы действительно можете справиться. - person Didier A.; 01.11.2014
comment
@didibus Как вы думаете, почему соображения безопасности должны создавать неудобства в разработке? Я никогда ничего не говорил о продюсировании. Что касается локализации сообщений об ошибках, то на всем веб-сайте уже есть эта проблема, и люди, похоже, с ней справляются. - person Trejkaz; 03.11.2014
comment
@Trejkaz Я не уверен, о каком веб-сайте вы говорите. Я говорю о кодах ошибок HTTP. Они стандартные, и они возвращаются веб-серверами как стандартные ошибки. Если бы веб-сервер вернул более подробную информацию об ошибке, это потенциально могло бы привести к утечке данных о вашем сайте. Таким образом, он возвращает только стандартную ошибку. Подробности вы можете посмотреть в журналах. Точно так же браузер реагирует на ошибку, отображая соответствующее сообщение для пользователя, такой браузер может сопоставить код ошибки с соответствующим локальным языком для языка пользователя. Что касается ваших собственных ошибок, вы можете реализовать что угодно. - person Didier A.; 05.11.2014
comment
@Trejkaz Протокол имеет встроенную поддержку обработки ошибок. В этом суть кодов состояния ошибки. HTTP-ответ может включать код ошибки и сообщение об ошибке, чтобы HTTP-запросчик знал, что что-то пошло не так, и подробно об этом. По умолчанию HTTP-серверы не возвращают много деталей в ответе на ошибку из соображений безопасности, а также удобства для пользователя. Некоторые браузеры, такие как IE, даже заменяют ответ об ошибке собственной ошибкой, чтобы сделать его более удобным для пользователей. - person Didier A.; 07.11.2014
comment
@Trejkaz Большинство серверов можно настроить так, чтобы вместо этого возвращались подробные ошибки, что полезно во время разработки. Имейте в виду, что это ошибки HTTP-сервера. Если вы используете что-то еще для генерации ваших ответов, например PHP, ASP.NET или RAILS и т. Д., Они должны будут добавить детали в ответ об ошибке и передать этот ответ серверу или сказать серверу, чтобы он отправил ответ об ошибке с данным сообщением об ошибке. Большинство из них также можно настроить для этого. - person Didier A.; 07.11.2014
comment
@Trejkaz Не знаю, какой веб-сервер вы используете или какую внутреннюю часть используете, но вот как включить подробные ошибки в IIS7: http://www.iis.net/learn/troubleshoot/diagnosing-http-errors/how-to-use-http-detail-errors-in-iis - person Didier A.; 07.11.2014
comment
что вы имеете в виду под * handle *, когда говорите Вы должны перехватывать только те исключения, которые вы действительно можете обработать. - person user1451111; 14.06.2018

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

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

В целом я использую следующие правила:

  1. В моих компонентах и ​​библиотеках я перехватываю исключение только в том случае, если я собираюсь обработать его или сделать что-то на его основе. Или, если я хочу предоставить дополнительную контекстную информацию в исключении.
  2. Я использую общую попытку перехвата в точке входа в приложение или на самом высоком возможном уровне. Если возникает исключение, я просто регистрирую его и позволяю ему потерпеть неудачу. В идеале исключения никогда не должны попадать сюда.

Я считаю, что следующий код является запахом:

try
{
    //do something
}
catch(Exception)
{
   throw;
}

Такой код не имеет смысла и не должен включаться.

person JoshBerke    schedule 03.01.2009
comment
@Josh, хороший момент о проглатывании исключений, но я считаю, что есть несколько случаев, когда допустимо просто проглатывать исключения. В последнем проекте ваш фрагмент кода был обязательным, от него воняло. Регистрация их всех усугубила ситуацию. Мой совет: если вы не можете обработать исключение, постарайтесь не проглотить его. - person smaclell; 03.01.2009
comment
В целом, как я уже сказал, все зависит от приложения и конкретного контекста. Бывают случаи, когда я проглатываю исключения, хотя это бывает редко, и я не могу вспомнить, когда я делал это в последний раз ;-) Вероятно, это было, когда я писал свой собственный регистратор, и запись в журнал, и вторичный журнал терпели неудачу. - person JoshBerke; 04.01.2009
comment
Код служит точкой: вы можете установить точку останова при переходе. - person Rauhotz; 04.01.2009
comment
Слабое место: вы можете указать VS прерываться при возникновении любого возникшего исключения или сузить его и выбрать конкретное исключение. В VS2008 есть пункт меню под отладкой (вам нужно настроить панели инструментов, чтобы найти его) Вызываемые исключения - person JoshBerke; 04.01.2009
comment
Пример запаха кода имеет явный побочный эффект, даже в такой простой форме. Если // do something включает какие-либо try/finally блоки вокруг точки, которая выбрасывает, блоки finally будут выполняться перед блоком catch. Без try/catch исключение будет перемещаться до вершины стека без выполнения каких-либо finally блоков. Это позволяет обработчику верхнего уровня решать, выполнять ли блоки finally. - person Daniel Earwicker; 29.01.2010
comment
Пункт 2. - действительно отличная идея. - person neal aise; 02.08.2010

Я хотел бы порекомендовать еще один хороший источник по этой теме. Это интервью с изобретателями C # и Java, Андерсом Хейлсбергом и Джеймсом Гослингом соответственно, на тему проверенного исключения Java.

Отказ и исключения

Внизу страницы также есть отличные ресурсы.

Я склонен согласиться с Андерсом Хейлсбергом и вами в том, что большинство звонящих заботятся только о том, прошла ли операция успешно или нет.

Билл Веннерс: вы упомянули о проблемах масштабируемости и версионности в отношении отмеченных исключений. Не могли бы вы пояснить, что вы имеете в виду под этими двумя проблемами?

Андерс Хейлсберг: Начнем с управления версиями, потому что проблемы там довольно легко увидеть. Скажем, я создаю метод foo, который объявляет, что он генерирует исключения A, B и C. Во второй версии foo я хочу добавить кучу функций, и теперь foo может генерировать исключение D. Для меня это критическое изменение. добавьте D в предложение throws этого метода, потому что существующий вызывающий этот метод почти наверняка не обработает это исключение.

Добавление нового исключения в предложение throws в новой версии приводит к нарушению клиентского кода. Это похоже на добавление метода к интерфейсу. После публикации интерфейса он остается неизменным для всех практических целей, потому что любая его реализация может иметь методы, которые вы хотите добавить в следующую версию. Поэтому вместо этого вам нужно создать новый интерфейс. Точно так же с исключениями вам придется либо создать совершенно новый метод с именем foo2, который генерирует больше исключений, либо вам придется перехватить исключение D в новом foo и преобразовать D в A, B или C.

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

Андерс Хейлсберг: Нет, потому что во многих случаях людям все равно. Они не собираются обрабатывать ни одно из этих исключений. В их цикле сообщений есть обработчик исключений нижнего уровня. Этот обработчик просто вызовет диалоговое окно, в котором сообщается, что пошло не так, и продолжается. Программисты защищают свой код, написав повсюду try finally, поэтому они вернутся правильно, если произойдет исключение, но на самом деле они не заинтересованы в обработке исключений.

Предложение throws, по крайней мере, так, как оно реализовано в Java, не обязательно заставляет вас обрабатывать исключения, но если вы не обрабатываете их, оно заставляет вас точно подтверждать, какие исключения могут пройти. Это требует, чтобы вы либо перехватывали объявленные исключения, либо помещали их в свой собственный пункт throws. Чтобы обойти это требование, люди делают смешные вещи. Например, они украшают каждый метод «выдает исключение». Это полностью лишает возможности эту функцию, и вы просто заставляете программиста писать еще больше суетной чуши. Это никому не помогает.

РЕДАКТИРОВАТЬ: добавлены дополнительные сведения о преобразовании

person Gant    schedule 03.01.2009
comment
Спасибо за это! Я обновил свой вопрос информацией о вашем ответе! - person AtariPete; 04.01.2009
comment
Похоже, мистер Хейлсберг оправдывает обработку исключений Pokemon. Одна из огромных проблем с дизайном исключений в Java и C # заключается в том, что слишком много информации закодировано в типе исключения, в то время как информация должна храниться в экземплярах исключения, недоступных в любым последовательным способом. Исключения должны распространяться вверх по стеку вызовов до тех пор, пока все представленные аномальные условия не будут разрешены; к сожалению, тип исключения - даже если он распознан - мало что говорит о том, разрешена ли ситуация. Если исключение не распознано ... - person supercat; 08.03.2013
comment
... ситуация еще хуже. Если код вызывает FetchData и генерирует исключение неожиданного типа, он не может узнать, означает ли это исключение только то, что данные недоступны (в этом случае способность кода обойтись без него разрешит это), или это означает, что ЦП горит, и система должна выполнить безопасное отключение при первой возможности. Похоже, мистер Хейлсберг предполагает, что код должен предполагать первое; возможно, это лучшая стратегия с учетом существующих иерархий исключений, но, тем не менее, она кажется неприятной. - person supercat; 08.03.2013
comment
Я согласен, что throws Exceptin - это нелепо, потому что почти все может вызвать исключение, вы должны просто предположить, что это может произойти. Но когда вы указываете исключения, такие как throws A, B, C, это просто аннотация, для меня ее следует использовать как блок комментариев. Это все равно, что сказать: «Эй, клиент моей функции», вот подсказка, может быть, вы хотите разобраться с A, B, C, потому что эти ошибки могут произойти при использовании меня. Если вы добавите D в будущем, это не имеет большого значения, если с ним не будут разбираться, но это все равно, что добавить новую документацию, О, кстати, теперь также было бы полезно поймать D. - person Didier A.; 01.11.2014

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

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

  • Для удобства обслуживания всегда регистрируйте исключения, чтобы, когда вы начнете видеть ошибки, журнал поможет указать вам место, где, вероятно, возникла ошибка. Никогда не оставляйте printStackTrace() или тому подобное. Скорее всего, один из ваших пользователей в конечном итоге получит одну из этих трассировок стека и будет совершенно нулевым знанием относительно того, что с ней делать.
  • Перехватывать исключения, которые вы можете обработать, и только те, и обрабатывать их, не просто выбрасывают их в стек.
  • Всегда перехватывайте определенный класс исключений, и обычно вы никогда не должны перехватывать тип Exception, вы, скорее всего, проглотите важные исключения.
  • Никогда (никогда) не ловить Error !!, что означает: Никогда не ловить Throwable, поскольку Error являются подклассами последнего. Errors - это проблемы, с которыми вы, скорее всего, никогда не справитесь (например, OutOfMemory или другие проблемы с JVM)

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

person Yuval Adam    schedule 03.01.2009
comment
Проверенные исключения не являются проблемой в C #, потому что в нем их нет. - person cletus; 04.01.2009
comment
Imho, иногда полезно отлавливать ошибки: я вспоминаю написанное мною Java-приложение с очень интенсивным использованием памяти. Я поймал OutOfMemory-Ex и показал пользователю сообщение о том, что ему не хватает памяти, что он должен выйти из других программ, и сказал ему, как запустить jvm с выделенным дополнительным пространством кучи. Думаю, это помогло. - person Lena Schimmel; 04.01.2009

Вам следует перехватывать только те исключения, с которыми вы можете справиться. Например, если вы имеете дело с чтением по сети, а время ожидания соединения истекает, и вы получаете исключение, вы можете попробовать еще раз. Однако, если вы читаете по сети и получаете исключение IndexOutOfBounds, вы действительно не можете справиться с этим, потому что вы не знаете (ну, в этом случае вы не знаете), что его вызвало. Если вы собираетесь вернуть false, -1 или null, убедитесь, что это для определенных исключений. Мне не нужна библиотека, которую я использую, возвращая ложь при чтении по сети, когда возникшее исключение - это нехватка памяти в куче.

person Malfist    schedule 03.01.2009

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

Ex.

try
{
   sendMessage();

   if(message == success)
   {
       doStuff();
   }
   else if(message == failed)
   {
       throw;
   }
}
catch(Exception)
{
    logAndRecover();
}

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

person Holograham    schedule 03.01.2009

Все вышеперечисленное кажется разумным, и часто на вашем рабочем месте может быть определенная политика. У нас мы определились с типами Exception: SystemException (не отмечено) и ApplicationException (отмечено).

Мы договорились, что SystemException вряд ли удастся восстановить, и что они будут обработаны один раз наверху. Чтобы предоставить дополнительный контекст, наши SystemException расширены, чтобы указать, где они произошли, например RepositoryException, ServiceEception и т. Д.

ApplicationExceptions может иметь такое же деловое значение, как InsufficientFundsException, и должно обрабатываться клиентским кодом.

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

person Community    schedule 03.01.2009

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

Иногда может случиться так, что возникшее исключение не будет иметь смысла для вызывающего абонента (т. Е. Это сетевое исключение), и в этом случае вам следует заключить его в исключение, специфичное для домена.

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

person wds    schedule 03.01.2009

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

Также рассмотрите возможность использования фильтра исключений при регистрации исключений в диагностических целях. VB имеет языковую поддержку для фильтров исключений. В ссылке на блог Греггма есть реализация, которую можно использовать с C #. Фильтры исключений имеют лучшие свойства для возможности отладки по сравнению с перехватом и повторным выбросом. В частности, вы можете зарегистрировать проблему в фильтре и позволить исключению продолжать распространяться. Этот метод позволяет присоединить отладчик JIT (Just in Time), чтобы получить полный исходный стек. Повторный бросок обрезает стопку в том месте, где она была повторно брошена.

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

// throws NumberNotHexidecimalException
int ParseHexidecimal(string numberToParse); 

bool TryParseHexidecimal(string numberToParse, out int parsedInt)
{
     try
     {
         parsedInt = ParseHexidecimal(numberToParse);
         return true;
     }
     catch(NumberNotHexidecimalException ex)
     {
         parsedInt = 0;
         return false;
     }
     catch(Exception ex)
     {
         // Implement the error policy for unexpected exceptions:
         // log a callstack, assert if a debugger is attached etc.
         LogRetailAssert(ex);
         // rethrow the exception
         // The downside is that a JIT debugger will have the next
         // line as the place that threw the exception, rather than
         // the original location further down the stack.
         throw;
         // A better practice is to use an exception filter here.
         // see the link to Exception Filter Inject above
         // http://code.msdn.microsoft.com/ExceptionFilterInjct
     }
}

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

person Steve Steiner    schedule 03.01.2009
comment
Мне нравится шаблон TryXXX в .NET. - person JoshBerke; 04.01.2009

Я предлагаю вам воспользоваться стандартной библиотекой для используемого вами языка. Я не могу говорить за C #, но давайте посмотрим на Java.

Например, java.lang.reflect.Array имеет статический метод set:

static void set(Object array, int index, Object value);

Способ C был бы

static int set(Object array, int index, Object value);

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

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

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

person slim    schedule 04.01.2009
comment
Это очень правильный комментарий, уважайте язык и то, как он традиционно решает такие проблемы. Не привносите мышление C в мир Java. - person AtariPete; 04.01.2009

Если вы собираетесь поймать Exception и вернуть false, это должно быть очень конкретное исключение. Вы этого не делаете, вы ловите их все и возвращаете false. Если я получу MyCarIsOnFireException, я хочу сразу об этом узнать! Остальные исключения меня могут не волновать. Таким образом, у вас должен быть стек обработчиков исключений, которые говорят «эй, эй, здесь что-то не так» для некоторых исключений (повторное генерирование или перехват и повторное генерирование нового исключения, которое лучше объясняет, что произошло), а для других просто возвращают false.

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

Изменить: Что касается вопроса о том, чтобы обернуть все в try / catch, я думаю, что ответ - да. Исключения в вашем коде должны быть настолько редкими, чтобы код в блоке catch выполнялся так редко, что вообще не влиял на производительность. Исключением должно быть состояние, когда ваш конечный автомат сломался и не знает, что делать. По крайней мере, повторно вызовите исключение, которое объясняет, что происходило в то время, и содержит исключение catch внутри него. «Исключение в методе doSomeStuff ()» не очень полезно для тех, кто должен выяснить, почему он сломался, пока вы в отпуске (или на новой работе).

person jcollum    schedule 03.01.2009
comment
Не забывайте, что установка блока исключений тоже стоит ... - person devstuff; 04.01.2009

Моя стратегия:

Если исходная функция вернула void, я изменяю ее, чтобы вернуть bool. Если произошло исключение / ошибка, верните false, если все в порядке, верните true.

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

Вместо bool может быть возвращена строка, содержащая описание ошибки.

В каждом случае перед возвратом чего-либо регистрируйте ошибку.

person Germstorm    schedule 03.01.2009

Здесь есть отличные ответы. Я хотел бы добавить, что если вы все-таки получите что-то вроде того, что вы опубликовали, по крайней мере, распечатайте больше, чем трассировку стека. Скажите, что вы делали в то время, и Ex.getMessage (), чтобы дать разработчику шанс побороться.

person dj_segfault    schedule 03.01.2009
comment
я полностью согласен. Я сделал только Ex.printStackTrace (); в качестве примера того, что я делал в улове (т.е. не перебрасывал). - person AtariPete; 04.01.2009

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

Тем не менее, при разумном использовании они творит чудеса в удобочитаемости, но вы должны просто следовать двум простым правилам:

  • используйте их (экономно) на низком уровне, чтобы выявлять проблемы с обработкой библиотек и передавать их обратно в основной логический поток. Большая часть необходимой нам обработки ошибок должна исходить от самого кода как части самих данных. Зачем ставить особые условия, если возвращаемые данные не особенные?

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

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

Павел.

person Paul W Homer    schedule 04.01.2009

Я могу немного опоздать с ответом, но обработка ошибок - это то, что мы всегда можем изменить и развить со временем. Если вы хотите узнать больше об этой теме, я написал об этом сообщение в моем новом блоге. http://taoofdevelopment.wordpress.com

Удачного кодирования.

person Community    schedule 01.02.2011