Когда использовать утверждение, и когда использовать исключения


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

например,

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}

Не могли бы вы указать, как утверждение вписывается здесь? Должен ли я использовать утверждение?

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

11 102

11 ответов:

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

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

отметим, что if(group != null) не утверждение, то есть просто условное.

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

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

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

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

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

также вы должны прочитать статья Oracle о assert чтобы увидеть больше случаев, когда использовать или не использовать - утверждать.

как правило:

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

следующий код из вашего вопроса-это плохой стиль и потенциально багги

try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}

проблема в том, что вы не знаете, что исключение означает, что группа не найдена. Также возможно, что service() вызов вызвал исключение, или что он вернулся null, который затем вызвал NullPointerException.

когда вы ловите" ожидаемое " исключение, вы должны поймать только исключение, что вы ждем. Поймав java.lang.Exception (и особенно не регистрируя его), вы затрудняете диагностику / отладку проблемы и потенциально позволяете приложению наносить больший ущерб.

согласно этому документу http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general, "оператор assert подходит для проверки непубличных предварительных условий, постусловий и инвариантов классов. Проверка общедоступных предварительных условий должна по-прежнему выполняться проверками внутри методов, которые приводят, в частности, к документированным исключениям, таким как IllegalArgumentException и IllegalStateException."

Если вы хотите узнать больше о предварительное условие, постусловие и инвариант класса, проверьте этот документ: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions. Он также содержит примеры использования утверждений.

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

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

Я предполагаю, что вывод заключается в том, что это немного осталось до команды разработчиков для каждого приложения, чтобы определить границы assert vs exceptions.

тестирование на null будет ловить только нули, вызывающие проблемы, тогда как try / catch, как у вас есть, будет ловить любой ошибка.

в целом, try / catch безопаснее, но немного медленнее, и вы должны быть осторожны, чтобы поймать все виды ошибок, которые могут возникнуть. Поэтому я бы сказал, что используйте try / catch - однажды код getGroup может измениться, и вам просто может понадобиться эта большая сеть.

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

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

Итак, используя утверждения в Java

  1. является более сжатым средством написания условия / бросить блок
  2. позволяет вам повернуть эти проверки включено-выключено через параметры JVM. Обычно я бы оставил эти проверки все время, если они не влияют на производительность во время выполнения или не имеют аналогичного штрафа.

см. раздел 6.1.2 (утверждения против другого кода ошибки) документации Sun по следующей ссылке.

http://www.oracle.com/technetwork/articles/javase/javapch06.pdf

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

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