Почему я должен использовать утверждения?

У меня никогда не было идеи об утверждениях — зачем вообще их использовать?

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

Тесты (в отладке) прошли нормально, но теперь мы хотим заняться гонками (релизом)! Должны ли мы отказаться от всей безопасности, потому что при тестировании не было проблем?

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

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


person Community    schedule 04.07.2009    source источник
comment
Вам никогда не приходило в голову, и все же вы никогда не удалите их? Вы как будто соглашаетесь и не соглашаетесь одновременно.   -  person ralphtheninja    schedule 04.07.2009
comment
Утверждения используются только ленивыми программистами, которые не хотят программировать обработку ошибок. Если вы знаете, что возможна ошибка, обработайте ее. Если это невозможно, то и утверждать нечего.   -  person Justin    schedule 07.08.2009
comment
Джастин, утверждения нужны не для этого. Утверждения предназначены для сильного взрыва, когда происходит что-то, что буквально никогда не должно происходить (потому что это указывает на ошибку программирования). Они не предназначены для обработки повседневных предсказуемых ошибок.   -  person Mike Daniels    schedule 07.08.2009


Ответы (19)


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

Именно в этом суть.

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

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

Утверждения в основном сводятся к следующему: «Зачем отлавливать ошибки, с которыми вы не можете справиться?»

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

У меня никогда не было идеи об утверждениях — зачем вообще их использовать?

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

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

А как насчет проверки того, что двигатель установлен? Нужно ли нам проверять это во время гонки?

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

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

Это в основном разница. Исключение существует, чтобы помочь пользователю, обрабатывая ошибки, которые можно обработать.

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

Квадратный корень из четырех никогда не должен равняться трем. Ошибка просто невозможна. Если это происходит, логика вашей программы просто нарушена. Неважно, сколько обработки ошибок мы обрабатываем, это то, что нужно отлавливать во время разработки или не отлавливать вообще. Если бы мы использовали обработку исключений, чтобы проверить эту ошибку и обработать ее, что будет делать исключение? Сообщите пользователю, что программа принципиально сломана. Никогда не использовать его?

Электронная почта от разработчика могла бы достичь этого. Зачем встраивать это в программный код? Это пример проблемы, которая просто не должна возникать. Если это так, мы должны вернуться и исправить программу. Никакая другая форма обработки ошибок невозможна.

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

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

person jalf    schedule 07.08.2009
comment
Я думаю, что многие посты здесь верны, но этот очень близок к моей философии. Утверждения помогают мне при разработке, при создании моего приложения. Я предпочитаю, чтобы он останавливался и генерировал аварийный дамп, как только произошла ошибка, которую я не ожидаю при разработке. Гонка :-). +1 ! - person yves Baumes; 07.08.2009
comment
Это, вероятно, то, что делает команда Формулы-1 при разработке нового двигателя (например). Они испытали свой двигатель на цепи с множеством датчиков и других вещей. Когда люди в яме обнаруживают ошибки, они просят водителя остановиться в яме, чтобы внести некоторые исправления, и т. д., и т. д., и т. д. К тому времени они достигают своей цели: двигатель, который готов к .. производству. :-) - person yves Baumes; 07.08.2009
comment
Если мы участвуем в гонке без двигателя, нам конец. А как насчет того, чтобы участвовать в гонке без тормоза? Машина по-прежнему заводится нормально, но гонщик был бы облажался в середине гонки, если бы никто не позаботился проверить это во время старта гонки. В этом случае, если мы обнаружим ошибку, еще не поздно что-то с этим сделать — мы можем прервать процесс и не подвергать опасности жизнь водителя. Строго говоря, если что-то обходит утверждение (в производстве), программа может делать что угодно, включая удаление конфиденциальных файлов. - person kizzx2; 05.12.2010
comment
@kizzx2: перед гонкой аналогично во время тестирования/компиляции, где утверждения удобны. во время гонки соответствует во время выполнения. Так что я действительно не понимаю, как это противоречит всему, что я сказал. Автомобиль не должен участвовать в гонке без тормозов. Такая ошибка должна быть обнаружена до запуска автомобиля. Точно так же некоторые ошибки в программном обеспечении должны быть отловлены до запуска программы: во время компиляции/тестирования, например, через assert. Если вы вступаете в гонку без тормозов, сигнализация об ошибке не очень помогает. Слишком поздно решать проблему безопасно. - person jalf; 05.12.2010
comment
Мои извинения - аналогии заходят так далеко. Я думаю, что мои тезисы можно резюмировать следующим образом: 1) Мы никогда не знаем, что невозможно — если бы мы знали, ни одно программное обеспечение не зависло бы. То, что мы считали невозможным (утверждения), вполне может произойти в продакшене. 2) Когда ошибочное утверждение не останавливается - программа перешла в неопределенное поведение. Я считаю безответственным позволять программе продолжать работу без какой-либо обработки ошибок. ------- Конечно, это не абсолютная правда. Некоторые программы (критически важные) требуют более тщательной проверки безопасности, а для некоторых шоу должно продолжаться (например, видеоигры). - person kizzx2; 06.12.2010
comment
@kizzx2: неважно, что мы знаем, что это невозможно. Важно то, что есть вещи, с которыми невозможно управиться. Есть ошибки, которые, если они происходят, означают, что с приложением что-то настолько фундаментально не так, что мы не можем с этим справиться. Единственный разумный ответ — обнаружить это во время разработки и исправить. Если это произойдет в дикой природе, мы ничего не сможем сделать. Конечно, мы можем ловить исключения, пока коровы не вернутся домой, а потом что? Что мы делаем с ними? Как мы выздоравливаем? Мы не можем, потому что все пошло так неправильно, что мы не можем доверять нашему коду. - person jalf; 06.12.2010
comment
Утверждения являются средством отладки для программиста, чтобы убедиться, что такие ситуации не возникают. Но если они это делают, то мы глубоко увязаем в неопределенном поведении, даже если мы попытаемся с этим справиться. - person jalf; 06.12.2010
comment
скажем, ваш код содержит векторную математическую библиотеку. В вашей функции нормализации вы вполне можете определить утверждение, проверяющее, что результирующий вектор действительно имеет длину 1, как и ожидалось. Но какую обработку ошибок вы бы добавили, чтобы решить проблему, если она возникнет в рабочей среде? Какие исключения вы собираетесь перехватывать и что вы собираетесь делать, чтобы вернуть приложение в нужное русло? Что бы ни случилось, это, очевидно, сделало ненадежным даже наш самый простой код. Лучшее, что мы можем сделать, это следить за ним во время разработки и проверять, нормально ли он там себя ведет. - person jalf; 06.12.2010
comment
Конечно, любая ошибка, которую может обработать, должна обрабатываться должным образом. Там нет аргумента. Но утверждения предназначены для обнаружения ошибок, которые невозможно обработать, потому что вы по колено в безвыходной ситуации, которую вы не могли предсказать. Вы можете предсказать, что могут возникнуть ошибки нехватки памяти, или что файл может быть заблокирован, или любые другие ошибки, и их следует обрабатывать. Но некоторые концептуально невозможны. Вызов sqrt должен возвращать неотрицательное число, нормализованный вектор должен иметь длину 1, запись в память должна выполняться в память и так далее. Эти вещи просто должны работать. - person jalf; 06.12.2010
comment
другой момент - это количество. Я могу позволить себе добавлять утверждения везде, даже к самым нелепым вещам, потому что я знаю, что они отключены в рабочей среде, поэтому они не повредят производительности. Но если я начну писать код обработки ошибок для каждой записи в память, чтобы убедиться, что данные, записываемые в память, совпадают с теми, которые мы получаем при обратном чтении, тогда приложение просто остановится (и Мне пришлось бы обрабатывать ошибки в моих обработчиках ошибок, и компилятору, вероятно, не хватило бы памяти, пытаясь справиться с миллиардами строк кода, которые мне пришлось бы написать, чтобы охватить все) - person jalf; 06.12.2010
comment
По этой причине даже самый параноидальный программист не проверяет миллионы потенциальных ошибок. Каждая отдельная строка кода содержит элементы, для которых мог бы быть написан код обработки ошибок, но вы никогда этого не сделаете. Это действительно безответственно? Это просто реалистично. Если запись в память не работает, вы ничего не можете сделать, так зачем пытаться с этим справиться? Но если во время разработки вы обнаружите, что ваше оборудование не справляется с записью в память должным образом, то у вас есть время так или иначе с этим справиться. - person jalf; 06.12.2010
comment
@jalf Это очень важные моменты. Правда, в областях, критичных к производительности, очень разумно предпочесть утверждения исключениям. Я думаю, что следует сосредоточиться на том, в вашей области, насколько важно быть строгим в отношении условий ошибки? Например, если бы я писал для архитектуры, где segfault приведет к остановке всей машины (не я думаю, что это редкость в дни Windows 95), он просто обязан заранее обнаружить нулевой указатель, перехватить исключение и красиво выйти. - person kizzx2; 06.12.2010
comment
Я думаю, что разница здесь на самом деле заключается в конкретной области — поэтому я не говорю, что мы никогда не должны использовать assert — хотя я предлагаю, чтобы для большинства обычных программистов исключения были разумным значением по умолчанию. Например, если я нахожусь в подпрограмме транзакций банковской базы данных, ответственный поступок состоит в том, чтобы немедленно остановиться, когда я обнаружу, что программа ведет себя странно, а не рисковать, идя дальше. - person kizzx2; 06.12.2010
comment
С другой стороны, я, вероятно, не буду возражать против того, чтобы рискнуть этим в видеоигре — было бы безответственно останавливать шоу игрока, даже если игра могла бы попытаться продолжить. Используя пример записи в память - если вы записываете в отображаемый в память ввод-вывод для управления физическим устройством, вам лучше немедленно остановиться, если запись в память ведет себя странно. - person kizzx2; 06.12.2010
comment
Я согласен с тем, что разумное использование утверждений на самом деле поощряется. У нас нет времени оценивать каждую ошибку (опять же, в зависимости от вашего домена. Если бы я писал программу для запуска ракет, это не оправдание). Утверждения служат так же хорошо, как и громкие комментарии. - person kizzx2; 06.12.2010
comment
Я думаю, что мой вывод заключается в том, что исключения могут быть обработаны, но даже когда они необработаны, они служат защитой от неопределенного поведения, а также своего рода рудиментарным отчетом об ошибках (лучше, чем возможная ошибка сегмента или удаление случайного файла). Более подробно я написал в своем блоге cfc .kizzx2.com/index.php/my-take-on-assertions-vs-exceptions не стесняйтесь комментировать :) - person kizzx2; 06.12.2010
comment
@kizzx2: но если вы обнаружите, что программа ведет себя странно в банковской транзакции, это очевидный пример того, когда следует использовать обработку исключений. Я бы никогда не предложил использовать там утверждения. Опять же, утверждения только помогают разработчику в проверке того, что программа действительно ведет себя так, как я ожидаю. Если есть какой-либо шанс, что он может вести себя по-другому во время выполнения, то мне определенно нужна надежная обработка ошибок. Но для простых проверок работоспособности вещи, которые на самом деле не имеют смысла обрабатывать как ошибки, но которые просто облегчают отладку, предоставляя мне гарантию того, что эти инварианты все еще сохраняются. - person jalf; 06.12.2010
comment
каждое утверждение, которое не было инициировано, является для меня доказательством того, что эта часть приложения работает должным образом. Это полезно знать при отладке ошибки. Это означает, что мы можем исключить отдельные источники ошибок. - person jalf; 06.12.2010
comment
как программисты, мы должны принимать вещи на веру, независимо от того, насколько строгую обработку ошибок вы пишете. Как вы проверяете, работает ли ваш обработчик исключений? Вы должны доверять этому. Как проверить правильность записи в память? Вы должны доверять этому. Вы должны верить, что различные инструкции делают то, что должны, и вы должны верить, что вредоносные приложения не просто перезапишут память вашего процесса. Все эти вещи, которым мы доверяем, не могут быть разумно обработаны как ошибки. Это было бы слишком медленно и слишком сложно, независимо от домена. - person jalf; 06.12.2010
comment
Но мы можем утверждать, что да, гравитация все еще работает сегодня, и да, значение, которое я написал по адресу X, все еще существует. Все те вещи, которым мы просто доверяем, но которые во время отладки приятно иметь возможность подтвердить. - person jalf; 06.12.2010
comment
@jalf Спасибо за столь подробное объяснение, этот вопрос и ваш ответ на него очень помогли мне понять значение утверждений и когда их использовать. Вы изложили это так, как никто другой не смог бы, спасибо, очень информативно. - person Bharat; 19.08.2016
comment
На практике проблема в том, что разработчики никогда не используют приложение как реальный пользователь. Следовательно, fatalError, который вы разместили, может никогда не быть достигнуто во время разработки. Но если пользователь его использует, то каким-то образом он ломает приложение. Но на данный момент у нас нет фатальных ошибок. Будет ли правильным выбором добавление журнала рядом с каждым fatalError? Очевидно нет. Я думаю, вам нужно что-то, что объединяет их вместе, чтобы вы могли иметь утверждения разработки + журналы ошибок... - person Honey; 01.05.2018
comment
@ Дорогая, по сути, нередко можно увидеть что-то вроде assert(condition); if (!condition) {} - этого никогда не должно происходить, но если это произойдет, мы сделаем все возможное, чтобы попытаться справиться с этим. Я также нахожусь в процессе того, чтобы утверждения моих компаний были тестом во время выполнения и регистрировались при неудачах, потому что, честно говоря, утверждения великолепны, но люди, которые делают гоночные машины, не водят их как гонщики F1. - person UKMonkey; 04.08.2020

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

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

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

person cdleary    schedule 04.07.2009
comment
Обратите внимание, что статья по-прежнему доступна на Интернет-архив. - person Qantas 94 Heavy; 31.08.2014

Из Code Complete 2: «Используйте обработку ошибок для ожидаемых условий; используйте утверждения для условий, которые никогда не должны возникать».

Часто цитируемый пример — проверка нуля в знаменателе перед делением.

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

Модульные тесты не являются заменой утверждений.

person Nosredna    schedule 04.07.2009
comment
используйте утверждения для условий, которые никогда не должны возникать. Я всегда думал, что это очень похоже на обработку исключений. - person geowa4; 04.07.2009
comment
обработка исключений предназначена для вещей, о которых вы знаете, почему они происходят, и с которыми вы можете справиться внутри программы. Если утверждение терпит неудачу, что-то настолько неправильно, что вы не знаете, что делать, и программа должна выйти. - person Janusz; 04.07.2009
comment
@George IV: Разница в том, что утверждения предназначены для вещей, которые, по вашему мнению, невозможны, если ваша программа верна. Исключения для вещей, которые не должны происходить в том смысле, что ваша процедура/программа не может работать, если они происходят. Следовательно, библиотеки иногда выдают исключения для вещей, в которых приложение будет утверждать, поскольку библиотека не знает, является ли проблема немыслимой с точки зрения программы (например, нехватка памяти: в некоторых средах вы можете кодировать, чтобы избежать этого, в другие нельзя). - person Steve Jessop; 04.07.2009
comment
Модульные тесты не заменяют утверждения. Можете ли вы добавить больше, чтобы различать их? - person Honey; 01.05.2018

Потому что они облегчают отладку.

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

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

person David Norman    schedule 04.07.2009

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

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

person Brian Neal    schedule 04.07.2009

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

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

person geowa4    schedule 04.07.2009

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

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

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

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

person Larry Watanabe    schedule 04.07.2009
comment
утверждения замедляют код. Мы использовали их в видеоиграх, и они присутствовали во время большей части тестирования. Их пришлось разбирать после. Вы не утверждаете на GameCube. - person Nosredna; 04.07.2009

Утверждения бесценны при рефакторинге, я думаю. Если вы хотите заменить alogrihm1() алгоритмом2(), вы можете использовать их оба и утверждать, что результаты равны. Затем вы можете постепенно отказаться от алгоритма1()

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

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

person psquare    schedule 04.07.2009

В Code Complete есть раздел, который говорит что-то вроде. Каждый раз, когда вы пишете if без каких-либо других параметров, вы, возможно, что-то упускаете.

Это как этот код

int i = 1
i = i++ 

Обычный программист никогда не будет думать о том, что произойдет, если i будет отрицательным в более позднем коде. Существует небольшая вероятность того, что ваш код вызовет переполнение, а такие языки, как java, перейдут от max int к min int, и вы получите очень большое отрицательное число. Это все случаи, о которых вы обычно говорите. Это никогда не случится. Но что делает ваша программа, если это произойдет? Итак, если вы знаете, что есть что-то, что, по вашему мнению, никогда не произойдет, проверьте это или нет и поместите утверждение false в предложение else, которое никогда не произойдет, вместо того, чтобы программировать оператор else. Таким образом, ваша программа должна полностью рухнуть в тот момент, когда вы перестанете быть уверены в том, что она делает. В производственном коде должно быть что-то отличное от сбоя, например, информирование пользователя, сопровождающего и последующий выход.

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

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

person Janusz    schedule 04.07.2009

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

В Debug, если условие ложно, отладчик запускается в этой точке кода.

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

person Pete Kirkham    schedule 04.07.2009

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

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

A(char* p)
{
    if(p == NULL)
        throw exception;

    B(p);
    C(p);

}

B(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

C(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

D(char* p)
{
    assert(p != NULL);
    do stuff;
}

Вместо вызова «if(p == NULL) throw exception;» 5 раз, вы просто вызываете его один раз, чтобы вы уже знали, что это не NULL при вводе B(), C() и D(). В противном случае утверждение завершится на этапе разработки, потому что вы «изменили код!» не из-за «ввода пользователя».

Это может заставить код работать намного быстрее в релизной версии, потому что все, что вам нужно сделать, это вызвать gcc с «-DNDEBUG», поэтому все утверждения не будут скомпилированы, а все «ненужные проверки» будут удалены в исполняемом файле.

person Jeremiah Dicharry    schedule 13.07.2015

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

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

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

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

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

person Chris Tsang    schedule 06.05.2020

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

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

person Steve Jessop    schedule 04.07.2009

Я использую его в основном для тестов во время разработки. Например, вот тест дыма моей библиотеки utf-8 Всякий раз, когда я вношу изменения в код библиотеки, я запускаю тесты, и если возникает ошибка, срабатывает утверждение. Конечно, я мог бы использовать полноценную инфраструктуру модульного тестирования, но для моих целей подходят только утверждения.

person Nemanja Trifunovic    schedule 04.07.2009

Не могу не процитировать "Непременных Кальвина и Гоббса" с. 180:

Прежде чем спускаться с такого крутого холма, нужно всегда проверять безопасность своих саней.
Верно.
Ремни безопасности? Нет.
Сигналы ? Нет.
Тормоза? Нет.
Рулевое управление ? Нет.
ХУЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕЕ

person denis    schedule 07.08.2009

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

a = set()
a.add('hello')
assert 'hello' in a

or

a = 1;
assert a == 1; // if ram corruption happened and flipped the bit, this is the time to assert

Что касается исключений, это то, с чем вы имеете дело программно:

while True:
  try:
    data = open('sample.file').read()
    break // successfully read
  except IOError:
    // disk read fail from time to time.. so retry
    pass

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

person vtlinh    schedule 27.09.2013

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

Для всего остального сгенерируйте исключение.

person balajeerc    schedule 05.08.2015

Для других ответов на этот вопрос

Макрос assert() используется для проверки условий или допущений, которые не должны встречаться в программе. Например, индекс массива всегда должен быть > 0. Другое предположение может быть 2+2 == 3+1.

Таким образом, используя assert(), мы можем проверить такие предположения, и пока они оцениваются как истинные, наша программа работает нормально. Когда они ложны, программа завершается.

подробнее здесь https://www.softwaretestinghelp.com/assert-in-cpp/

person Peter    schedule 31.05.2020

Я НИКОГДА не использую утверждения в своем коде, я их страстно ненавижу. Я понимаю необходимость проверки и обработки ошибок, но предотвратить ошибку, которая приведет к сбою вашей программы, путем сбоя вашей программы самостоятельно .... честно говоря, я не вижу преимущества.

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

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

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


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

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

В большей части производственного кода, который я видел, я заметил в основном два способа справиться с этим: намазать утверждения по всему коду, а затем оставить хороший набор в производстве. У этого есть приводящая в бешенство тенденция просто закрывать приложение для пользователя, я еще не видел, чтобы Assert изящно подвел систему .... он просто подвел ее ... бум ... ушел ... конечный пользователь просто сказал: «WTF ошибка утверждения по адресу 0x330291ff!!!"

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

НИ ОДИН СПОСОБ не поможет получить хорошую стабильную систему. Конечно, вы можете использовать утверждения в своем бета-коде и удалить их все в своем производственном коде... но какого черта вам удалять свои сети безопасности, потому что это производство. Я был бы очень удивлен, если бы все эти проверки нанесли вред производительности вашей системы.

Создайте себе хорошую схему обработки исключений и... ей-богу... ОСТАВЬТЕ ЭТО ЗДЕСЬ, вы получите гораздо более значимую информацию о вашей системе, и если все сделано правильно, всегда в контексте, чем наличие какой-то глубокой библиотеки, выбрасывающей утверждения, потому что чего-то не хватает.

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

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

И да... обычно код, который дает сбой в продакшене, редко имеет мое имя сверху.

person Newtopian    schedule 04.07.2009
comment
они именно для этого момента. в тот момент, когда закон Мерфи забирает вашу программу, и вы не знаете, что она делает потом. Если они вам не нравятся, вы можете удалить их и добавить обработку ошибок в позицию, но если обработка ошибок делает что-то другое, кроме отображения непредвиденной ошибки ... произошла, пожалуйста, свяжитесь со специалистом службы поддержки, это не место для утверждения и обработка ошибок в этом месте правильная. - person Janusz; 04.07.2009
comment
Если вы используете утверждения, то, по крайней мере, вы знаете, где ваша программа потерпела неудачу и какая внутренняя несогласованность вызвала ее неудачу. Если вы решите проигнорировать условия, которые могут привести к сбою утверждения, ваша программа может рухнуть в любое время или даже выдать неправильные результаты без каких-либо жалоб. Ни один из этих случаев не лучше для пользователя, но оба они хуже для программиста, пытающегося отладить (и для всех в цепочке технической поддержки между пользователем и отладчиком). - person user57368; 04.07.2009
comment
Да, когда-нибудь они сработают в производственном коде. Это ХОРОШО, если ваша программа предоставляет какие-то средства аварийного сохранения (при условии, что в ней изначально есть какой-то документ). Когда вы попадаете в безвыходную ситуацию, вы должны НЕ i> попытаться продолжить. Сохраните, НЕ ПЕРЕЗАПИСЫВАТЬ и выйдите. - person Loren Pechtel; 04.07.2009
comment
@Janusz - Лично я думаю, что всплывающее окно с ошибкой или утверждение в значительной степени эквивалентны, то есть почти бесполезны, если ваш стек программного обеспечения становится очень большим и просто очень сильно ухудшает работу конечного пользователя. - person Newtopian; 04.07.2009
comment
@unknown ... Я могу сделать то же самое с исключением, я не вижу, где утверждение может сделать больше, чем уже может исключение. Если пользователь моей библиотеки решит, что эта исключительная ситуация не так уж плоха, и решит, тем не менее, продолжить, то это его ошибка, а не моя. Кроме того... он вполне может быть прав, для вас, создателя библиотеки, это может быть непоправимой ошибкой, но для него у него может быть план на случай непредвиденных обстоятельств, который он может использовать. Утверждения не дали бы ему такой гибкости. - person Newtopian; 04.07.2009
comment
@Loren - ничего себе ... так что у вас всегда есть обзор всего программного стека и вы всегда можете решить, когда он должен выйти из строя !!?? теперь есть кто-то, кого я бы не хотел видеть в своей команде. Если вы полагаетесь на более низкие библиотеки, чтобы сломать стек, когда они не имеют правильных состояний, я предлагаю вам расширить свой кругозор и начать учиться справляться с исключительными ситуациями. Поначалу будет сложно... весь этот лишний код, но поверьте мне... ваш парень из техподдержки полюбит вас за это, и через 20 лет может предотвратить увольнение ВАС. - person Newtopian; 04.07.2009
comment
Чувак, тебе действительно нужно лучше разбираться в вещах, прежде чем пытаться направлять других. Единственное, что вы говорите мне, это то, что вы понятия не имеете, что такое утверждения. 1. Утверждения! = Исключения 2. Они не приводят к сбою вашей программы, они останавливают выполнение. Большая большая разница. 3. большинство пользователей никогда не прикоснутся к коду с утверждениями. Они есть только в отладочных сборках. и так далее.... - person Casper Leon Nielsen; 25.10.2012
comment
@CasperLeonNielsen, если вы читаете первый ответ здесь, он ссылается на сообщение, в котором утверждается, что утверждения должны быть фактически оставлены в производственном коде. Я согласен с тем, что пытается сделать автор, в том, что приложение не должно пытаться восстановиться после ошибки, если оно рискует перевести его в нестабильное состояние. Я не согласен с тем, что Asserts является подходящим инструментом для этого. Я также категорически не согласен с наличием кода, который отличается между отладкой и выпуском. Теперь вы не можете контролировать, что будет делать компилятор, но для частей, которые вы можете контролировать, я действительно хочу, чтобы это было постоянным и предсказуемым. - person Newtopian; 26.10.2012
comment
[...] не следует пытаться восстановиться после ошибки, если это может привести к нестабильному состоянию. Я не согласен с тем, что Asserts является подходящим инструментом для этого. Я согласен, если вы имеете в виду, что это не инструмент для выхода из критических ситуаций, как вы описываете, но это не инструмент для этого. Вот почему я пытаюсь указать, что вы, кажется, не понимаете цели утверждений. Утверждения нужны, в основном, для двух целей: документирования предположений и информирования разработчиков. - person Casper Leon Nielsen; 26.10.2012
comment
утверждать (0). Никакой закон подлости не разрушит это утверждение. - person Alice; 12.06.2014