Когда утверждения должны оставаться в рабочем коде? - PullRequest
147 голосов
/ 20 августа 2008

Обсуждение продолжается на comp.lang.c ++. Модерируется вопрос о том, следует ли сохранять в рабочем коде утверждения, которые по умолчанию существуют только в C ++ в отладочных сборках.

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

Под утверждением я подразумеваю:

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

Я не обязательно говорю о C или C ++.

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

Каково ваше мнение / опыт?

Приветствия

Карл

См. Связанный вопрос здесь


Отзывы и обновления

Привет, Грэм,

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

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

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


Немного не по теме, но важный момент в обсуждении.

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

Карл


Thomas

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

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

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

Карл

Ответы [ 16 ]

76 голосов
/ 08 января 2009

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

54 голосов
/ 20 августа 2008

Позвольте мне процитировать код Пола Стива Макконнелла. Раздел «Утверждения» - 8.2.

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

Однако позже в том же разделе дается этот совет:

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

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

33 голосов
/ 20 мая 2010

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

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

http://c2.com/cgi/wiki?ShipWithAssertionsOn

17 голосов
/ 21 января 2014

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

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

Более интересный вопрос заключается в следующем: когда вы отключаете утверждения на этапе тестирования?

8 голосов
/ 23 сентября 2014

Утверждения не должны никогда оставаться в рабочем коде. Если конкретное утверждение кажется полезным в производственном коде, то оно не должно быть утверждением; это должна быть проверка ошибок во время выполнения, то есть что-то вроде этого: if( condition != expected ) throw exception.

Термин «утверждение» стал означать «проверку только на время разработки, которая будет не проводиться на месте».

Если вы начнете думать, что утверждения могут дойти до поля, тогда вы неизбежно также начнете высказывать и другие опасные мысли, например, задаваясь вопросом, действительно ли какое-либо данное утверждение стоит делать. Нет такого утверждения, которое не стоит делать. Вы никогда не должны спрашивать себя: «Должен ли я утверждать это или нет?» Вам следует только спросить себя: «Я что-то забыл утверждать?»

6 голосов
/ 20 августа 2008

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

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

5 голосов
/ 25 ноября 2008

В моем C ++ я определяю REQUIRE (x), который похож на assert (x), за исключением того, что он выдает исключение, если утверждение не выполняется в сборке выпуска.

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

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

4 голосов
/ 20 августа 2008

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

2 голосов
/ 20 августа 2008

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

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

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

2 голосов
/ 20 августа 2008

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

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

...