Фундаментальные алгоритмы и структуры данных в Delphi - страница 18

стр.

Проверка утверждений может применяться тремя способами: предусловие, постусловие и инвариант. Предусловие (pre-condition) - это утверждение, находящееся в начале функции. Оно однозначно указывает, какое условие, касающееся окружения и входных параметров, должно соблюдаться перед выполнением функции. Например, предположим, что создана функция, которой в качестве параметра передается объект. При этом разработчик решил, что функции не должен передаваться nil. Помимо доведения этой информации до всех разработчиков, он должен в начале функции вставить утверждение, которое будет проверять, передается ли функции nil. В таком случае, если сам разработчик функции или кто-то из его коллег забудет о существующем ограничении, предупреждение напомнит об этом.

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

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

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

Классическим примером может служить исключение "List index is out of bounds" (Индекс в списке вышел за допустимые пределы), особенно тот случай, когда используется индекс -1. Ошибка подобного типа вызвана тем, что программист не проверяет индекс элемента перед тем, как записать или считать его из TList. Код объекта TList проверяет все передаваемые ему индексы элементов. Если индекс находится вне допустимого диапазона, возникает исключение. Пользователь приложения не может вызвать такую ошибку (по крайней мере, это покажется глубоко бессмысленным для большинства пользователей). Ошибка возникает исключительно из-за недостаточного объема проведенного тестирования. По мнению автора, это исключение должно быть утверждением.

А теперь рассмотрим другой случай. Предположим, что мы разрабатываем функцию, которая должна разворачивать данные из файла, например, из архива. Формат сжатого файла достаточно сложен, по крайней мере, он считается простой последовательностью битов, и все последовательности выглядят примерно одинаково. Если в последовательности битов функция разархивирования встретит ошибку (например, последовательность исчерпана, но логически она не закончилась), будет это утверждением или же исключением? По мнению автора, это должно быть простым исключением. Вполне вероятно, что функции в качестве входных данных будут переданы поврежденные файлы или файлы, которые не являются архивами в требуемом формате. Очевидно, что это ошибка не программиста. Она полностью вызвана внешними условиями.

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

Комментарии

Это правило выглядит достаточно просто:

----

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

----

Протоколирование

Рассмотрим еще одно средство из арсенала защитного программирования -протоколирование (logging). Под протоколированием здесь понимается вставка дополнительного кода, закрытого директивами компилятора, который записывает в файл состояние или значения основных переменных.