Лучшие практики для управления исключением в Java или [закрытом] C#

Ответ Botz на 100% правильный, вот короткое объяснение:

Когда вы пишете метод (общий или нет) и объявляете типы параметров, которые принимает метод, вы определяете контракт:

Если вы дадите мне объект, который знает, как выполнять множество вещей, которые знает тип T, я могу доставить либо «a»: возвращаемое значение объявляемого типа, либо 'b': какое-то поведение, которое использует этот тип.

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

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

Проблема в том, что, когда вы входите в метод, вы понятия не имеете, дали ли они вам IJumpRope или PiFactory. Кроме того, когда вы идете вперед и используете метод (при условии, что вы получили его, чтобы магически скомпилировать), вы не уверены, что у вас есть Fisher или AbstractConcreteMixer. В основном это делает все более запутанным.

Решение вашей проблемы является одной из двух возможностей:

  1. Определить несколько методов, которые определяют каждое возможное преобразование, поведение , или что-то еще. Это ответ Ботца. В мире программирования это называется перегрузкой метода.
  2. Определите базовый класс или интерфейс, который знает, как выполнять все, что вам нужно для метода, и один метод принимает только этого типа. Это может быть связано с завершением работы string и Exception в небольшом классе, чтобы определить, как вы планируете сопоставлять их с реализацией, но тогда все очень просто и легко читается. Я мог бы приехать через четыре года и прочитать ваш код и легко понять, что происходит.

Который вы выбираете, зависит от того, насколько сложным будет выбор 1 и 2, и насколько он может быть расширяемым .

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

public interface IHasMessage
{
    string GetMessage();
}

public void test(string a, IHasMessage arg)
{
    //Use message
}

Теперь все, что вам нужно, это методы, которые преобразуйте string и Exception в IHasMessage. Очень легко.

117
задан 9 revs, 4 users 59% 23 May 2017 в 10:31
поделиться

14 ответов

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

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

  1. необходимо только поймать исключения, которые можно на самом деле обработать. Просто ловля исключений не является правильным поступком в большинстве случаев. Существует несколько исключений (например, регистрирующиеся и упорядочивающие исключения между потоками), но даже для тех случаев необходимо обычно повторно бросать исключения.
  2. у Вас не должно определенно быть большого количества операторов попытки/выгоды в Вашем коде. Снова, идея состоит в том, чтобы только поймать исключения, которые можно обработать. Можно включать самый важный обработчик исключений для превращения любых необработанных исключений во что-то несколько полезное для конечного пользователя, но иначе Вы не должны пытаться поймать каждое исключение в каждом возможном месте.
61
ответ дан user 24 November 2019 в 02:09
поделиться

пробуйте/ловите форму блоков второй набор логики, встроенной по первому (основному) набору, как таковому, они - отличный способ загнать нечитабельный, трудно отладить запутанный код.

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

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

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

Кроме этих двух типов обработки ошибок, вся остальная часть кода в середине должна быть свободна и свободна от кода попытки/выгоды и ошибочных объектов. Тем путем это работает просто и как ожидалось неважно, где Вы используете его, или что Вы делаете с ним.

Paul.

0
ответ дан Paul W Homer 24 November 2019 в 02:09
поделиться

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

0
ответ дан dj_segfault 24 November 2019 в 02:09
поделиться

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

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

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

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

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

0
ответ дан Germstorm 24 November 2019 в 02:09
поделиться

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

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

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

0
ответ дан jcollum 24 November 2019 в 02:09
поделиться

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

Также рассматривают использование Фильтр Исключения при входе исключений в диагностических целях. VB имеет поддержку языка фильтров Исключения. Ссылка на блог Greggm имеет реализацию, которая может использоваться от C#. Фильтры исключения имеют лучшие свойства для debuggability по выгоде и переброску. Конкретно можно зарегистрировать проблему в фильтре и позволить исключению продолжить распространять. Тот метод позволяет присоединению JIT (Как раз вовремя) отладчик иметь полный исходный стек. Перебросок отключает стек в точке, это было повторно брошено.

случаи, где 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 или не являетесь большим количеством вопроса о стиле. Вопросом ловли всех исключений и глотания их не является проблема стиля. Удостоверьтесь, что непредвиденным исключительным ситуациям позволяют распространить!

1
ответ дан Steve Steiner 24 November 2019 в 02:09
поделиться

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

, Например, java.lang.reflect. Массив имеет помехи set метод:

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

путь C был бы

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

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

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

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

1
ответ дан slim 24 November 2019 в 02:09
поделиться

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

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

ApplicationException, с могла иметь бизнес, означающий как InsufficientFundsException, и должна быть обработана клиентским кодом.

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

2
ответ дан 24 November 2019 в 02:09
поделиться

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

Напр.

try
{
   sendMessage();

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

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

3
ответ дан Holograham 24 November 2019 в 02:09
поделиться

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

5
ответ дан Malfist 24 November 2019 в 02:09
поделиться

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

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

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

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

8
ответ дан Yuval Adam 24 November 2019 в 02:09
поделиться

Я хотел бы рекомендовать другой хороший источник по теме. Это - интервью с изобретателями C# и Java, Anders Hejlsberg и James Gosling соответственно, по теме Контролируемой исключительной ситуации Java.

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

внизу страницы существуют также большие ресурсы.

я склонен соглашаться с Anders Hejlsberg и Вами, о которых только заботится большинство вызывающих сторон, успешна ли операция или нет.

Bill Venners : Вы упомянули масштабируемость и проблемы управления версиями относительно контролируемых исключительных ситуаций. Вы могли разъяснить то, что Вы подразумеваете под теми двумя проблемами?

Anders Hejlsberg : давайте запустимся с управления версиями, потому что проблемы довольно легко видеть там. Скажем, я создаю нечто метода, которое объявляет, что выдает исключения A, B, и C. В версии два из нечто я хочу добавить набор функций, и теперь нечто могло бы выдать исключение D. Это - повреждающееся изменение для меня для добавления D к пункту бросков того метода, потому что существующая вызывающая сторона того метода почти наверняка не обработает то исключение.

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

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

Anders Hejlsberg : Нет, потому что в большом количестве случаев, люди не заботятся. Они не собираются обрабатывать любое из этих исключений. Существует обработчик исключений нижнего уровня вокруг их цикла сообщения. Тот обработчик просто собирается поднять диалоговое окно, которое говорит, что пошло не так, как надо, и продолжить. Программисты защищают свой код путем записи finally's попытки везде, таким образом, они отступят правильно, если исключение произойдет, но они на самом деле не интересуются обрабатыванием исключений.

пункт бросков, по крайней мере, способ, которым это реализовано в Java, не обязательно вынуждает Вас обработать исключения, но если Вы не обрабатываете их, это вынуждает Вас подтвердить точно, через который могли бы пройти исключения. Это требует, чтобы Вы или поймали объявленные исключительные ситуации или поместили их в Ваш собственный пункт бросков. Для работы вокруг этого требования люди делают смешные вещи. Например, они украшают каждый метод, "выдает Исключение". Это просто полностью побеждает функцию, и Вы просто заставили программиста записать больше gobbledy месива. Это не помогает никому.

РЕДАКТИРОВАНИЕ: Добавленный больше деталей о converstaion

9
ответ дан Gant 24 November 2019 в 02:09
поделиться

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

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

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

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

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

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

Код как это не служит никакому смыслу и не должен быть включен.

25
ответ дан JoshBerke 24 November 2019 в 02:09
поделиться

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

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

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

1
ответ дан wds 24 November 2019 в 02:09
поделиться