Когда утверждения должны оставаться в производственном коде?

Там обсуждение продолжается на comp.lang.С++.moderated о том, утверждаются ли утверждения, которые в С++ существуют только в отладочных сборках по умолчанию, должны храниться в производственном коде или нет.

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

По утверждению, я имею в виду:

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

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

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

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

Приветствия,

Карл

См. соответствующий вопрос здесь


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

Эй Грэм,

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

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

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


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

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

Карл


Томас,

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

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

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

Карл

Ответ 1

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

Ответ 2

Позвольте мне процитировать Кодекс Стива Макконнелла. Раздел об утверждении равен 8.2.

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

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

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

Говорят, вы не должны показывать эти сообщения assert конечным пользователям, потому что они не поймут их. Так? Конечные пользователи могут отправить вам электронное письмо с снимком экрана или текст сообщения об ошибке, который поможет вам отладить. Если пользователь просто говорит "он разбился", у вас меньше возможностей исправить его. Лучше было бы автоматически отправлять сообщения об ошибках утверждения через Интернет, но это работает только в том случае, если у пользователя есть доступ в Интернет, и вы можете получить их разрешение.

Ответ 8

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

Ответ 9

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

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

Ответ 10

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

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

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

Ответ 11

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

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

Однако скажем, что ваш fopen() документирован как всегда возвращающий действительный открытый дескриптор файла. Вы открываете файл и передаете его функции readfile().

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

Итак, readfile() {assert (fptr!= NULL);..} подходит в этом случае, хотя полномасштабная обработка ошибок не является (игнорирование того факта, что на самом деле чтение файла потребует некоторой системы обработки ошибок).

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

Ответ 12

Я никогда не поддерживаю их в критическом критическом коде.

Ответ 13

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

Я предлагаю пример

file = create-some-file();
_throwExceptionIf( file.exists() == false, "FILE DOES NOT EXIST");

против

file = create-some-file();
ASSERT(file.exists());

Как приложение обработает утверждение? Я предпочитаю старый метод try catch для решения фатальных ошибок.

Ответ 14

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

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

Ответ 15

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

Ответ 16

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

Есть несколько моментов, чтобы избежать включения утверждений в производственный код: 1. Вы не хотите, чтобы ваш конечный пользователь видел сообщение типа "НЕИСПРАВНОСТЬ", вызванная MyPrivateClass.cpp, строка 147. Конечный пользователь НЕ, ваш инженер QA. 2. УКАЗАНИЕ может влиять на производительность

Однако есть одна серьезная причина оставить утверждения: УКАЗАНИЕ может влиять на производительность и время, и, к сожалению, это иногда имеет значение (особенно во встроенных системах).

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

~ Ицик

Ответ 17

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

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

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