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

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

Например,

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
}

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

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

113
задан Machavity 5 October 2018 в 18:41
поделиться

8 ответов

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

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

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

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

.
79
ответ дан 24 November 2019 в 02:40
поделиться

Как правило:

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

.
15
ответ дан 24 November 2019 в 02:40
поделиться

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

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

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

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

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

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

.
164
ответ дан 24 November 2019 в 02:40
поделиться

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

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

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

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

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

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

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

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

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

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

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

Так что использование утверждений в Java

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

Похожие вопросы: