Потрясающие ответы уже здесь, особенно от Simucal. Я просто хочу добавить точку:
Наступательное программирование отлично подходит для отладки. По моему опыту, «рано проваливаться, часто проваливаться» можно рассматривать как установку ловушек для ошибок в вашем коде. Когда что-то идет не так - будь то утечка памяти, сбой памяти, неожиданный NULL и т. Д. - обычно намного легче увидеть проблему, если программа сразу же завершается неудачей (с соответствующими данными отладки, такими как стек вызовов).
Защитное программирование отлично подходит для производственных сред. После того, как ваше приложение было отправлено, вы, возможно, не захотите, чтобы ваши конечные пользователи когда-либо увидели симпатичный маленький диалог с надписью «необработанное исключение в foo ()». Это может быть замечательно, если ваше приложение находится в бета-версии, и вы все еще собираете отладочную информацию, но если вы поставляете стабильное приложение, вы можете просто не беспокоить пользователя загадочным выводом в редких случаях, когда что-то не получается. 1005 *
Иногда это можно сделать обоими способами. Я часто писал код на C следующим образом:
void foo(char* data) {
ASSERT(data);
if (!data) { return; }
// ... work with data
}
Если этот код скомпилирован в тестовой среде, оператор assert перехватывает условие ошибки. Если он скомпилирован в производственной среде, assert удаляется препроцессором и foo () завершается с ошибкой.
Исключения являются более выразительными и гибкими, чем утверждения, и существуют различные способы управления ими, так что приложение в начале тестовой среды дает сбой и обрабатывается при регистрации ошибок в производственной среде. В зависимости от типа проекта, этот вид дизайна может иметь смысл для вас.