2009-05-28 2 views

ответ

5

Assert, по крайней мере, в .NET, используется для тестирования в основном. Его конкретное использование ставится лаконично here:

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

* the condition should never be false if the code is correct, 
* the condition is not so trivial so as to obviously be always true, and 
* the condition is in some sense internal to a body of software. 

В производстве код, я бы порекомендовал первым Способ; или try/catch, если «что-то плохое» никогда не ожидается; если это исключительное условие.

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

Я видел утверждения в производственном коде; обычно в design-by-contract style code. Я вижу их гораздо чаще в модульных тестах.

1

IMHO, assert - заявить разработчику в среде отладки, что происходит что-то неожиданное (неправильное). Не все утверждения должны быть критически важными, и разработчики должны ставить утверждения на реальные сбои.

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

1

Используйте утверждение, когда что-то плохое никогда не произойдет, если код работает правильно. Пример:

int div(int a, int b) { 
    assert(b != 0); 
    return a/b; 
} 

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

Использовать if() ... return, когда может произойти ошибка, с которой можно справиться. Например, открытие файла может завершиться неудачей и должно быть обнаружено и обработано программой - сбой не выводит программу в неизвестное состояние.

0

Простой ответ - оба, но второй более важен. Утверждение проверяет конструктивное предположение, поэтому перед вызовом fn() у меня были бы предварительные условия, например. что данный ресурс может быть доступен. Утверждение, как правило, ничего не делает в коде выпуска, хотя и не обязательно. Если важно, чтобы ваша функция gn требовала, чтобы что-то было правдой, чтобы работать правильно, eithers использует оператор if и возвращает код ошибки, или генерирует исключение. Утверждение обычно ничего не делает в коде выпуска и, таким образом, ваша функция может произойти сбой в этой ситуации.

Смотрите также более подробные ответы, данные this question

0

Это действительно зависит от языка/среды выполнения, и характер ошибки.

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

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

«Возвратить ложную» вещь склонна к ошибкам (люди b/c забывают проверить возвращаемое значение), поэтому я буду использовать ее только в том случае, если доступны ни утверждения, ни исключения.

3

Рассмотрим даже использовать исключение, когда «некоторые вещи плохое случилось» = что-то исключительное ...

0

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

3

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

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

+0

Да, это моя точка зрения. Я использую assert() для проверки инвариантов в моей программе. Когда такие инварианты не соблюдаются, поскольку вызов assert генерирует coredump для моего приложения (при его отладке), я уверен, что не пропущу такую ​​проблему. Кроме того, я ожидаю, что последующие «разработчики» заметят, что что-то не так, когда приложение рушится ... Хотя простой оператор возврата может в конечном итоге привести к дампу некоторых строк в файле, которые разработчик мог бы избежать. Я не имею в виду, что вы можете избежать if() тестов. Я просто хочу сказать, что assert() - это способ гарантировать, что разработчики были сильно уведомлены о возникшей проблеме. –

1

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

0

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

В некоторых случаях я бы тогда реализовал вторую функцию с дополнительными параметрами со значениями по умолчанию и обрабатывал исключение, например StrinToIntegerDef (string, default), которое возвращает значение по умолчанию, когда строка не преобразуется в Integer.

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

Я бы предпочел значимые исключения, по крайней мере, формы assert (условие, сообщение), если язык позволяет это.

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

0

Используйте утверждения для мандата функции preconditions (условия, которые должны иметь значение true, если функция имеет какое-либо значение).

+0

Также инварианты и (в конце функций) постусловия. – Richard

2

Ваш «вернуться ложным» также называют GuardClause - как объясняет Уорд Каннингем:

... [G] uards подобны утверждениям в том, что как защитить последующий код из особых случаев.Охранники отличаются от от утверждений тем, что они производят материальный вклад в логику метода и, следовательно, не могут быть безопасны опущены как часть оптимизации. I заимствовал термин охранник от EwDijkstra при именовании этого шаблона.

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

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

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

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