Тестовые примеры И утверждения утверждений

Код в этом вопросе заставил меня задуматься

assert(value>0); //Precondition
if (value>0)
{
  //Doit
}

Я никогда не пишу оператор if. Достаточно заявить о себе / все, что вы можете сделать. «Сбои рано, сбои часто»

В CodeComplete говорится:

  • Оператор assert делает приложение правильным
  • If-test делает приложение надежным

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

assert(value >= 0 );  //Precondition
assert(value <= 90);  //Precondition
if(value < 0)         //Just in case
  value = 0;
if (value > 90)       //Just in case
  value = 90;
//Doit

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

Перефразируя CodeComplete: «Реальные программы < em> становится слишком беспорядочным, когда мы не полагаемся исключительно на утверждения ".

Вопрос: Я не прав, упрямый, глупый, слишком не оборонительный ...


person jan    schedule 11.09.2008    source источник
comment
Я согласен с тобой. Весь смысл утверждений заключается в выполнении проверок целостности во время тестирования, которые слишком дороги для выполнения в производственной среде. Их функция принципиально отличается от исключений.   -  person Galik    schedule 11.09.2017


Ответы (9)


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

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

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

person Tnilsson    schedule 11.09.2008
comment
Я думаю, проблема будет в том, что человек, решивший небольшую проблему, решил не тестировать программное обеспечение перед отправкой. Фаза тестирования не может быть пропущена разумно, а следовательно, и утверждения. - person Galik; 11.09.2017

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

Используйте операторы if для проверки ввода, который вы не контролируете: общедоступные интерфейсы, предназначенные для использования пользователем, тестирование ввода пользователем и т. Д.

Протестируйте свое приложение с помощью встроенных утверждений. Затем выполните развертывание без утверждений.

person Daren Thomas    schedule 11.09.2008

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

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

Я обычно бросаю исключение в if-statement, чтобы взять на себя роль утверждения, если они отключены.

assert(value>0);
if(value<=0) throw new ArgumentOutOfRangeException("value");
//do stuff
person Rik    schedule 11.09.2008
comment
Мне нравится выбрасывать исключение: оно всегда работает (производство и отладка), но зачем тогда писать утверждение assert? Это работает только в половине случаев. - person jan; 11.09.2008
comment
Я думаю, это просто вопрос условности. Когда я вижу неотмеченное исключение, причиной могли быть миллионы вещей. Когда я замечаю неудачное утверждение, я знаю, что облажался сам, и мне легче найти причину. - person Rik; 13.09.2008

Я бы не согласился с этим утверждением:

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

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

Что касается Asserts, я повторю других комментаторов, assert - это проверка времени отладки для автора кода, а не для клиентов кода.

person aku    schedule 11.09.2008

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

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

person Andrew    schedule 11.09.2008

Если я правильно помню из CS-класса

Предварительные условия определяют, при каких условиях определяется вывод вашей функции. Если вы сделаете свою функцию обработкой errorconditions, ваша функция определена для этих условий, и вам не нужен оператор assert.

Я согласен. Обычно и то, и другое не требуется.

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

person Mendelt    schedule 11.09.2008
comment
Проблема этого подхода в том, что сбой в результате незаконного вызова может произойти в совершенно другой части программы, что делает ее отладку кошмаром. - person Rik; 11.09.2008
comment
Я согласен. Думаю, мой ответ был неполным. Обычно я не удаляю утверждения в выпущенном коде. Я исправлю свой ответ. - person Mendelt; 11.09.2008

Я должен был сказать, что мне известно о том, что asserts (здесь) исчезают в производственном коде.

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

Для меня это ИЛИ ситуация:

(цитата Эндрю) «защитите от всех диапазонов недопустимого ввода, я бы не стал утруждать себя утверждением». -> напишите if-test.

(цитата аку) «неправильные входные значения простительны» -> напишите утверждение.

Я не могу стоять одновременно ...

person jan    schedule 11.09.2008

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

Проверьте входные данные, исходящие извне, с помощью условий if. Внешне это где угодно за пределами кода, который вы / ваша команда контролируете и тестируете.

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

person Andrew Johnson    schedule 11.09.2008

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

person Vinko Vrsalovic    schedule 11.09.2008
comment
Утверждения удалены из производственного кода по дизайну. Это особенность, а не ошибка. Вам просто нужно правильно их использовать. Если вам нужен тест в производственном коде, не используйте утверждения. - person Galik; 11.09.2017