Когда использовать утверждение, а когда использовать исключение - PullRequest
111 голосов
/ 24 декабря 2009

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

Например,

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 ]

160 голосов
/ 24 декабря 2009

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

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

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

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

79 голосов
/ 24 декабря 2009

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

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

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

Обратите внимание, что if(group != null) - это не утверждение, а условное выражение.

25 голосов
/ 24 декабря 2009

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

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

15 голосов
/ 24 декабря 2009

Как правило:

  • Используйте утверждения для внутренних проверок согласованности, когда вообще не имеет значения, если кто-то их отключает. (Обратите внимание, что команда 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 (и особенно не регистрируя его), вы усложняете диагностику / отладку проблемы и потенциально позволяете приложению наносить больший ущерб.

3 голосов
/ 23 октября 2012

Согласно этому документу 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. В нем также приведены примеры использования утверждений.

3 голосов
/ 24 декабря 2009

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

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

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

1 голос
/ 12 июля 2012

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

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

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

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

1 голос
/ 11 июня 2012

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

1 голос
/ 24 декабря 2009

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...