2009-07-04 2 views
40

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

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

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

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

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

+3

Похоже, вы знаете, почему, вы просто не согласны. Это нормально :) –

+0

У вас никогда не было этой идеи, и все же вы никогда их не удаляете? Похоже, вы согласны и не согласны в одно и то же время. – ralphtheninja

+0

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

ответ

2

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

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

15

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

Обычно цитируемый пример проверяет нуль в знаменателе перед делением.

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

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

+1

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

+5

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

+3

@George IV: Разница заключается в том, что утверждения относятся к вещам, которые, по вашему мнению, верны, если ваша программа правильная, невозможны. Исключения для вещей, которые «не должны» произойти в том смысле, что ваша рутина/программа не могут работать, если они это сделают. Следовательно, библиотеки иногда вызывают исключения для вещей, в которых приложение утверждало бы, поскольку библиотека не знает, не является ли проблема непостижимой из POV программы (например, из памяти: в некоторых средах, которые вы можете закодировать, чтобы избежать этого, в другие вы не можете). –

30

У Эндрю Кенига раньше был good philosophical discussion over the usage of exceptions and assertions in shipping code. В конце концов, вы защищаете от диких вещей, когда программа находится в непоправимо сломанном состоянии.

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

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

+3

Обратите внимание, что статья по-прежнему доступна в [Интернет-архиве] (https://web.archive.org/web/20090707025230/http://www.ddj.ком/блог/cppblog/Архивы/2007/07/assertions_vers.html). –

2

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

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

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

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

+2

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

1

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

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

int i = 1 
i = i++ 

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

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

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

-5

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

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

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

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


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

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

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

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

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

Создайте себе хорошую схему обработки исключений и ... богом ... ОСТАВЛЯЙТЕ ЭТО, вы получите гораздо более значимую информацию о нашей системе и, если это будет сделано всегда всегда в контексте, чем наличие каких-то глубоких бросков в библиотеке, потому что что-то пропал, отсутствует.

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

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

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

+1

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

+1

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

+0

Да, когда-нибудь они будут стрелять в производственный код. Это вещь * GOOD *, предполагающая, что ваша программа предоставляет некоторые средства для аварийного сохранения (при условии, что у него есть какой-то документ в первую очередь.) Когда вы сталкиваетесь с невозможной ситуацией, вы должны * НЕ * пытаться продолжить. Сохранить, * НЕ ЗАВЕРШИТЬ *, и выйти. –

7

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

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

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

2

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

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

2

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

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

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

0

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

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

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

0

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

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

0

Я использую его в основном для испытаний во время разработки. Например, here is the smoke test of my utf-8 library Всякий раз, когда я вношу изменения в код библиотеки, я запускаю тесты, и если будет введена ошибка, то будет инициироваться assert. Конечно, я мог бы использовать полномасштабную модульную тестовую среду, но для моих целей утверждения просто прекрасны.

0

Не может устоять при цитировании «Незаменимый Кальвин и Гоббс» с. 180:

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

34

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

Это точно точка.

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

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

Что утверждает, в основном сводится к тому, что «зачем беспокоиться об ошибках, с которыми вы не справитесь?»

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

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

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

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

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

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

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

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

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

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

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

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

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

+1

Я думаю, что многие сообщения здесь верны, но этот действительно близок к моей философии. Ассистенты помогают мне во время разработки при построении моего приложения.Я предпочитаю, чтобы он остановился и сгенерировал сбой при сбое, как только произошла ошибка, которую я не ожидаю при выполнении моей разработки .. race :-). +1! –

+0

Это, вероятно, то, что команда разработчиков формулы при разработке нового движка (например). Они подвергли свой двигатель испытанию на цепи со многими датчиками и другими материалами. Когда люди в яме обнаруживают ошибки, они просят водителя остановиться в яме, чтобы сделать коррекцию и т. Д. И т. Д. И т. Д. До того момента, когда они достигнут своей цели: двигатель, готовый к производству. :-) –

+0

«Если мы войдем в гонку без двигателя, мы ввернемся» Но как насчет «мы вошли в гонку без тормоза»? Автомобиль все еще начинает нормально, но водитель будет ввернут в середину гонки, если никто не позаботится проверить его во время начала гонки. В этом случае, если мы обнаружим ошибку, слишком поздно делать что-либо с этим - мы можем прервать эту вещь, а не подвергать опасности жизнь водителя. Строго говоря - если что-то обходит утверждение (в производстве), программа может делать что угодно, включая удаление конфиденциальных файлов. – kizzx2

0

Assertion следует использовать, когда вы делаете что-то вроде этого

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

или

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 

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

1

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

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

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; 
} 

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

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

0

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

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

Смежные вопросы