Java assert нарушен? - PullRequest
       35

Java assert нарушен?

25 голосов
/ 03 мая 2010

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

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

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

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

Все это подводит меня к моему вопросу (а этот является вопросом, а не оправданием для разглагольствования! Обещаю!):

Чего мне не хватает?

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

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

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


Редактировать: Просьба просить, просвещение получено.

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

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

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

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

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

assert reallyExpensiveSanityCheck(someObject) : someObject;

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

Ответы [ 12 ]

23 голосов
/ 03 мая 2010

assert - полезная часть Дизайн по контракту .В этом контексте утверждения можно использовать в:

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

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

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

19 голосов
/ 03 мая 2010

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

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

4 голосов
/ 03 мая 2010

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

Чего мне не хватает?

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

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

4 голосов
/ 03 мая 2010

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

4 голосов
/ 03 мая 2010

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

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

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

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

3 голосов
/ 03 мая 2010

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

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

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

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

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

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

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

3 голосов
/ 03 мая 2010

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

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

2 голосов
/ 03 мая 2010

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

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

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

или всплывающее окно сообщения или что-либо полезное в контексте.

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

1 голос
/ 17 июля 2011

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

Ошибка подтверждения должна указывать на ошибку проектирования в программе.

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

Утверждение полезно для читателей моего кода, так как они видят, что (1) я готов установить немного денег на это свойство; и (2) в предыдущих казнях и тестовых случаях свойство действительно сохранялось.

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

1 голос
/ 03 мая 2010

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

Если вы ожидаете, что в работе произойдет что-то плохое, например, listOfStuff будет иметь значение null, то либо ваш код недостаточно протестирован, либо вы не очищаете свой ввод перед тем, как позволите своему коду это сделать. В любом случае, «если (плохо) {выбросить исключение}» было бы лучше. Утверждения предназначены для времени тестирования / разработки, а не для производства.

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