Java, утверждают поврежденный?

При вводе по абсолютному адресу вокруг вопросов я недавно обнаружил assert ключевое слово в Java. Сначала, я был взволнован. Что-то полезное я уже не знал! Более эффективный путь ко мне для проверки законности входных параметров! Yay, учащийся!

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

Это походит на кошмар. Если я утверждаю, что не хочу, чтобы код продолжал идти если вход listOfStuff null, с какой стати я хотел бы то проигнорированное утверждение? Это походит, отлаживаю ли я часть производственного кода и подозреваю это listOfStuff возможно, был ошибочно передан a null но не смотрите доказательство файла журнала того инициированного утверждения, я не могу доверять этому listOfStuff на самом деле был отправлен допустимое значение; я также должен объяснить возможность, что утверждения, возможно, были выключены полностью.

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

Весь из которого приносит мне к моему вопросу (и это - вопрос, не оправдание за напыщенную речь! Я обещаю!):

Что я пропускаю?

Есть ли некоторый нюанс, который представляет реализацию Java assert намного более полезный, чем я даю ему кредит на? Способность состоит в том, чтобы позволить/запретить его из командной строки, на самом деле невероятно ценной в некоторых контекстах? Я - misconceptualizing это так или иначе, когда я предполагаю использование, это в производстве кодирует вместо операторов как if (listOfStuff == null) barf();?

Я просто чувствую, что существует что-то важное здесь, что я не добираюсь.

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


Править:

Просвещение запросило, просвещение получено.

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

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

assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;

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

Кроме того, я могу определенно видеть значение чего-то вроде этого:

assert reallyExpensiveSanityCheck(someObject) : someObject;

Моя благодарность всем, кто не торопился, чтобы помочь мне понять эту функцию; это очень ценится.

25
задан avandeursen 17 July 2011 в 15:53
поделиться

11 ответов

assert - это полезная часть Design by Contract. В этом контексте утверждения могут быть использованы в:

  • Проверке предусловий.
  • Проверки постусловий.
  • Проверки промежуточного результата.
  • Проверки инвариантов классов.

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

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

23
ответ дан 28 November 2019 в 18:17
поделиться

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

Например, я могу написать:

foo должно быть отличным от нуля и больше , чем 0

, или поместить это в тело программы:

assert foo != null;
assert foo.value > 0;

Они чрезвычайно ценны для документирования частных / package частные методы для выражения исходных инвариантов программиста.

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

3
ответ дан 28 November 2019 в 18:17
поделиться

Если утверждения нельзя отключить, то зачем они вообще должны существовать?

Если вы хотите проверить правильность ввода, вы можете легко написать

if (foobar<=0) throw new BadFoobarException();

или открыть окно сообщения или что-то еще, что полезно в контексте.

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

2
ответ дан 28 November 2019 в 18:17
поделиться

Это не дает прямого ответа на ваш вопрос о assert , но я бы рекомендовал проверить класс Preconditions в guava / google-collections . Это позволяет вам писать такие приятные вещи (используя статический импорт):

// throw NPE if listOfStuff is null
this.listOfStuff = checkNotNull(listOfStuff);

// same, but the NPE will have "listOfStuff" as its message
this.listOfStuff = checkNotNull(listOfStuff, "listOfStuff"); 

Похоже, что-то вроде этого может быть тем, что вы хотите (и это нельзя отключить).

1
ответ дан 28 November 2019 в 18:17
поделиться

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

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

3
ответ дан 28 November 2019 в 18:17
поделиться

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

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

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

0
ответ дан 28 November 2019 в 18:17
поделиться

Я думаю, это то, как интерпретируется и понимается использование assert.

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

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

Например, проверка объекта на null, допустим, разработчик написал приватный метод и вызвал его из двух мест (это не идеальный пример, но может работать для приватных методов) в классе, где он знает, что передает не null объект, вместо того, чтобы добавлять ненужную проверку if, поскольку на сегодняшний день вы знаете, что объект никак не может быть null. Но если кто-то завтра вызовет этот метод с аргументом null, в модульном тестировании разработчика это может быть поймано благодаря наличию assertion, и в конечном коде проверка if по-прежнему не нужна.

4
ответ дан 28 November 2019 в 18:17
поделиться

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

.
4
ответ дан 28 November 2019 в 18:17
поделиться

Утверждения в Java на самом деле не предназначены для проверки аргументов - специально оговорено, что утверждения не должны использоваться вместо старого доброго IllegalArgumentException (как и то, как они используются в языках на C). Они нужны скорее для внутренней проверки, чтобы вы могли сделать предположение о коде, которое не очевидно при взгляде на него.

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

19
ответ дан 28 November 2019 в 18:17
поделиться

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

Что я упускаю?

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

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

4
ответ дан 28 November 2019 в 18:17
поделиться

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

Если вы ожидаете, что в производстве произойдет что-то плохое, например, listOfStuff окажется null, то либо ваш код недостаточно протестирован, либо вы не обеззараживаете входные данные, прежде чем дать их коду. В любом случае, "if (bad stuff) { throw an exception }" было бы лучше. Утверждения предназначены для тестирования/разработки, а не для производства.

1
ответ дан 28 November 2019 в 18:17
поделиться
Другие вопросы по тегам:

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