Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

То, что утверждает, в основном сводится к: "Зачем беспокоиться об ошибках, с которыми вы не справитесь?"

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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

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

int i = 1
i = i++ 

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

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

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

Ответ 10

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

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

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); "5 раз вы просто вызываете его один раз, так что вы уже знаете, что это не NULL при вводе B(), C() и D(). В противном случае утверждение выйдет на этапе разработки, потому что вы" изменили код! ". не из-за" пользовательского ввода".

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

Ответ 11

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

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

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

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

Ответ 15

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

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

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

Ответ 16

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

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

Ответ 17

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

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

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

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


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

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

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

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

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

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

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

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

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