Глава 15.3 Инструменты Защитного Программирования (Defensive Programming)

January 28th, 2010 Begemot Posted in Учебники

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

Глава 15.3 Инструменты Защитного Программирования (Defensive Programming)

Часто вы можете обнаружить проблему только спустя некоторое время после возникновения логической ошибки. Если ошибочное значение не будет обнаружено вовремя, программа может успеть выполнить тысячи строчек кода перед тем как упасть или выдать мистический результат. Вы можете потратить уйму времени пытаясь найти реальную причину ошибки. Однако, стоит вам просто добавить проверки для своевременного обнаружения “плохих” значений, например, проверки значений аргументов функции, и ваш код сразу станет куда более стабильным. Тем самым вы можете оградить себя (и своих пользователей) от огромного количества потенциальных проблем. Эта техника носит название “защитное программирование”. Ваши классы и функции могут защитить себя как против “неправильного” использования вышестоящим кодом, так и против внутренних логических ошибок. Учитывая то, что большинство этих проверок, удаляются компилятором из финальной сборки, вам не приходиться платить за них размером файла или скоростью выполнения.

Как вы наверное уже догадались, в самом коде библиотеки выполняется огромное количество разнообразных проверок для обеспечения надежности, и вы точно также можете использовать те же макросы и функции в своем коде. Существует три основных семейства макросов: вариации на тему wxASSERT, wxFAIL и wxCHECK. wxASSERT показывает сообщение об ошибке если условие аргумента ложно, эта проверка осуществляется только в отладочной сборке. wxFAIL всегда генерирует сообщение об ошибке, таким образом она эквивалентна конструкции wxASSERT(false). Эта проверка также отсутствует в финальной-версии программы. wxCHECK проверяет условие на истинность и осуществляет выход из функции с возвратом заданного значения, если условие не выполняется. В отличии от двух других групп макросов, wxCHECK присутствует и выполняется (правда уже без показа сообщения) и в финальной версии программы. Эти макросы имеют модификации, позволяющие вам выводить собственное сообщение об ошибке.

Давайте посмотрим несколько примеров использования этих макросов:

// Найдем сумму двух положительных чисел
int AddPositive(int a, int b)
{
    // Проверим, положительно ли 'а'
    wxASSERT(a > 0);

    // Проверим, положительно ли 'b' и выдадим свое сообщение об
    // ошибке еcли что
    wxASSERT_MSG(b > 0, wxT("Второе число должно быть положительное!"));

    int c = a + b;
    // Вернем -1 если результат отрицателен или равен 0
    wxCHECK_MSG(c > 0, -1, wxT("Результат должен быть положительным!"));

    return c;
}

Макросы wxCHECK2 и wxCHECK2_MSG предназначены для выполнения произвольной операции вместо простого возврата из процедуры, если условие проверки не выполняются. wxCHECK_RET просто прерывает функцию, не возвращая ничего и используется, соответственно, в void-функциях. Информацию по редко используемым макросам wxCOMPILE_TIME_ASSERT и wxASSERT_MIN_BITSIZE, вы с легкостью найдете в справке.

Рисунок 15-1 показывает диалог сообщения об ошибке, появляющийся, если условие проверки не выполняется (равно false). Пользователь может остановить программу (Yes), проигнорировать ошибку (No) или проигнорировать сразу все дальнейшие предупреждения (Cancel). Если программа выполняется под управлением отладчика, остановка приведет к вызову прерывания отладчика, в результате вы перейдете к линии кода, в которой была обнаружена проблема и сможете посмотреть значения переменных в этой точке.

Рисунок 15-1. Сообщение об ошибке (Assertion alert)

image

Related:

10 Responses to “Глава 15.3 Инструменты Защитного Программирования (Defensive Programming)”

  1. А если функция void как вней должен выглядеть второй аргумент wxCHECK…
    void Test(int a)
    {
    wxCHECK(a>0, ?????)
    }

  2. wxCHECK нельзя применять для void функций, есть специальный макрос wxCHECK_RET ( condition, message )
    К сожалению версии без message нет – этот момент мне не нравится, имхо не доработка, так что пишем

    wxCHECK_RET(cond, wxEmptyString)

  3. Спасибо. Полезная информация

  4. А так не работает?
    wxCHECK(a>0, void(0))

  5. незнаю, не пробовал, и так можно?:)

  6. Можно везде, но не в конструкторе и деструкторе. Также можно еще немного сократить конструкцию до
    wxCHECK(a>0, void());

  7. Перевод 5, 8, 19 глав книги Джулиана Смарта по wxWidgets.
    Ссылки:
    http://www.megaupload.com/?d=F0UQHV7U
    http://upload.com.ua/get/901965917/Julian_Smart_5_8_19.rar

  8. отлично! здорово, так скоро всю книгу переведем:)

  9. Кстати, это не тот Сергей 🙂

  10. Да, я заметил 🙂