2009-01-07 5 views
20

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

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

+0

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

+0

Ну, это явно субъективно. По-моему, это также пограничный аргумент, но я бы подождал и посмотрел, что обсуждается. – EBGreen

+1

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

ответ

20

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

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

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

+2

Это походит на очень хорошую стратегию. Смешно, когда вы ищете людей, которые считают, что плохо, вы никогда не слышите от них. –

+2

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

1

Верно ли, что утверждение существует в сборке отладки, но не в сборке выпуска?

Если вы хотите проверить/утверждать что-то, не хотите ли вы сделать это в сборке выпуска, а также в сборке отладки?

+0

Ну, это конвенция. Это очень легко сделать, чтобы они появлялись в сборке Release тоже. И я думаю, что это часто хорошая идея. Тем не менее, может быть полезно иметь утверждения «Только для отладки», которые выполняют временные проверки, например, проверять, что список действителен каждый раз, когда выполняется операция списка. –

+0

Мне нравится выпускать версию программного обеспечения, которое разработчики фактически тестировали; поэтому я стараюсь удалить сборку «debug» из файла project/makefile, так что есть только одна версия, которая может быть построена (и протестирована, и отлажена, и выпущена). – ChrisW

+0

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

5

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

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

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

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

+1

Я знаю, что они используются для двух разных вещей, пожалуйста, снова прочитайте вопрос! –

6

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

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

  1. Код утверждение имеет заметное влияние на производительность
  2. Конкретное условие не является фатальным
  3. Иногда есть кусок кода, который может или не может быть мертвым. Мы добавим утверждение, в котором говорится, «как вы сюда попали». Не стрельба не означает, что код действительно мертв, но если QA отправляет мне электронное письмо и говорит «что означает это утверждение», теперь у нас есть репродукция, чтобы перейти к определенному фрагменту кода (это немедленно документировано, конечно).
+0

Точно мое мышление ... см. Мой комментарий на ответ Криса –

+0

Об этом пункте, см. Этот ответ и мое обновление в конце, ссылаясь на связанный с ним вопрос: http://stackoverflow.com/questions/117171/design-by- Контракт-тесты-по-утверждению или по исключению # 397873 –

+1

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

1

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

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

0

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

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

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

+0

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

3

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

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

+1

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

+0

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

3

Утверждения - отличная вещь, но ее нельзя путать с проверкой значения параметра/возвращаемого значения. Вы используете их в ситуациях, которые, как вы полагаете, не произойдут, а не в ситуациях, которые вы ожидаете, могут произойти.

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

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

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

0

Одна из причин для вето assert() заключается в том, что кодработает правильно, но не удается, если NDEBUG не определен. Или наоборот.

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

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

+0

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

+0

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

1

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

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

0

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

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