Контекст: я пишу серверное программное обеспечение для жизни, такое, которое остается неделями до загрузки следующей версии. Так что мои ответы могут быть склонны к крайне оборонительному коду.
Принцип.
Прежде чем мы углубимся в особенности использования assert
, важно понять принцип, лежащий в его основе.
assert
является важным инструментом в Защитное программирование . Это помогает проверять предположения (утверждать их на самом деле) и, таким образом, отлавливать программирование ошибок (чтобы отличить их от ошибок пользователя). Целью assert
является обнаружение ошибочных ситуаций, из которых восстановление, как правило, невозможно сразу.
Пример:
char const* strstr(char const* haystack, char const* needle) {
assert(haystack); assert(needle);
// ...
}
Альтернативы.
В С? Существует небольшая альтернатива. Если ваша функция не предназначена для передачи кода ошибки или возврата значения часового, и это должным образом документировано.
В C ++ исключения являются вполне приемлемой альтернативой. Однако assert
может помочь создать дамп памяти, чтобы вы могли точно видеть, в каком состоянии находится программа в момент обнаружения ошибочной ситуации (что помогает при отладке), в то время как исключение размотает стек и, таким образом, потеряет контекст (невный ...).
Кроме того, исключение может (к сожалению) быть обработано высокоуровневым обработчиком (или нежелательным уловком от такого же разработчика ( вы , конечно, этого не сделают)), в этом случае вы можете полностью пропустите ошибку, пока не станет слишком поздно.
Где НЕ использовать.
Во-первых, следует понимать, что assert
полезен только в Отладке кода. В версии NDEBUG определено, и код не генерируется. Как следствие, в версии assert
имеет ту же ценность, что и комментарий.
- Никогда не используйте его для проверок, которые необходимы для хорошего поведения программного обеспечения. Условия ошибки должны быть проверены и устранены. Всегда.
Во-вторых, следует понимать, что искаженный вклад является частью вашей жизни. Вы хотите, чтобы ваш компилятор отображал сообщение assert
каждый раз, когда вы делаете ошибку? Hum! Поэтому:
- Никогда не используйте его для проверки входных данных. Входные данные должны быть проверены и ошибки должны быть сообщены пользователю. Всегда.
В-третьих, следует понимать, что сбои не приветствуются. От вашей программы ожидается, что она будет работать без сбоев. Поэтому не следует поддаваться искушению оставить утверждения в режиме Release: код Release попадает в руки конечного пользователя и никогда не должен аварийно завершаться. В худшем случае он должен отключиться при отображении сообщения об ошибке. ожидается , что никакие пользовательские данные не будут потеряны во время этого процесса, и даже лучше, если после перезапуска пользователь будет возвращен туда, где он был: это то, что делают современные браузеры, например.
- Никогда не оставляйте подтверждения в Release.
Примечание: для серверного кода, после "подтверждения" утверждения, в большинстве случаев нам удается вернуться в исходное положение для обработки следующего запроса.
Где его использовать.
assert
включен в режиме отладки, поэтому его следует использовать для отладки. Всякий раз, когда вы тестируете новый код, всякий раз, когда запускается ваш набор тестов, когда программное обеспечение находится в руках в ваших (или ваших товарищах по команде), всякий раз, когда программное обеспечение находится в ваших руках отдела обеспечения качества. Утверждения позволяют выявлять ошибки и предоставляют полный контекст ошибки, чтобы вы могли восстановить .
- Используйте его во время циклов разработки и тестирования.
Еще лучше. Поскольку вы знаете, что код не будет выполняться в версии, вы можете позволить себе дорогие проверки.
Примечание: вы также должны проверить двоичный файл Release, если только для проверки производительности.
А в выпуске?
Что ж, в кодовой базе, над которой я работаю, мы заменяем недорогие утверждения (остальные игнорируются) конкретными исключениями, которые перехватываются только высокоуровневым обработчиком, который регистрирует проблему (с обратной трассировкой) , вернуть предварительно закодированный ответ об ошибке и возобновить обслуживание. Команда разработчиков уведомляется автоматически.
В развернутом программном обеспечении лучшие практики, которые я видел, подразумевают создание дампа памяти и передачу его обратно разработчикам для анализа , в то время как пытается не потерять какие-либо пользовательские данные и вести себя максимально вежливо. по отношению к несчастному пользователю. Мне очень приятно работать на стороне сервера, когда я размышляю над сложностью этой задачи;)