Сведения о вопросе

Electro Full

11:45, 2nd August, 2020

Теги

assert    

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

Просмотров: 379   Ответов: 16

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

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

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

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

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

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

Что ваш opinion/experience?

Овации,

Карл

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


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

Привет Грэм,

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

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

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


Небольшое отклонение от темы, но важный момент в обсуждении.

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

Карл


Томас,

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

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

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

Карл



  Сведения об ответе

ITSME

06:07, 29th August, 2020

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


  Сведения об ответе

lats

00:10, 26th August, 2020

Позвольте мне полностью процитировать код Стива McConnell. Раздел об утверждениях - это 8.2.

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

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

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

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


  Сведения об ответе

ASER

02:28, 7th August, 2020

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

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

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


  Сведения об ответе

lesha

00:08, 6th August, 2020

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

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

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


  Сведения об ответе

screen

18:14, 28th August, 2020

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

Термин 'assertion' стал означать " проверка development-time-only, которая не будет выполняться на поле."

Если вы начинаете думать, что утверждения могут попасть в поле зрения, тогда вы неизбежно начнете делать и другие опасные мысли, например, задаваться вопросом, действительно ли стоит делать какое-либо утверждение. Нет такого утверждения, которое не стоило бы делать. Вы никогда не должны спрашивать себя "should I assert this or not?" вы должны спрашивать только себя "Is there anything I forgot to assert?"


  Сведения об ответе

repe

21:46, 22nd August, 2020

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

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


  Сведения об ответе

park

02:14, 18th August, 2020

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

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

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


  Сведения об ответе

fo_I_K

18:30, 7th August, 2020

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


  Сведения об ответе

screen

00:06, 27th August, 2020

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

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


  Сведения об ответе

PROGA

21:26, 15th August, 2020

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

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

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


  Сведения об ответе

FAriza

21:32, 11th August, 2020

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


  Сведения об ответе

SKY

01:55, 27th August, 2020

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

то есть, если ваша программа opening/reading/closing файл, то невозможность открыть файл находится в области видимости-это реальная возможность, которую было бы небрежно игнорировать, другими словами. Таким образом, это должно иметь код проверки ошибок, связанный с ним.

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

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

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

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


  Сведения об ответе

PIRLO

17:07, 14th August, 2020

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

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

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

против

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

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


  Сведения об ответе

VCe znayu

21:38, 29th August, 2020

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

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


  Сведения об ответе

LIZA

04:09, 3rd August, 2020

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

Есть несколько моментов, чтобы избежать включения утверждений в производственном коде: 1. Вы же не хотите, чтобы ваш конечный пользователь увидел сообщение типа "ASSERTION failed MyPrivateClass.cpp line 147. Конечный пользователь - это NOT вы QA инженер. 2. ASSERTION может повлиять на производительность

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

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

~Yitzik


  Сведения об ответе

park

18:31, 25th August, 2020

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

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться