Написав предусловия (даже в виде комментариев), вы значительно повысите качество программы: это заставит вас задуматься о том, какие аргументы требует функция. Если вы не можете просто и ясно сформулировать эти требования в виде комментария, то, вероятно, вы плохо продумали свою программу. Опыт показывает, что такие предусловия и их проверки помогают избежать многих ошибок. Мы уже указывали, что ненавидим отладку; ясно сформулированные предусловия позволяют избежать конструктивных ошибок, а также устранить неправильное использование функций на ранних стадиях разработки программы. Вариант
int my_complicated_function(int a, int b, int c)
// Аргументы являются положительными и a < b < c
{
error("Неверные аргументы функции mcf");
// ...
}
сэкономит ваше время и силы по сравнению с более простым вариантом:
int my_complicated_function(int a, int b, int c)
{
// ...
}
5.10.1. Постусловия
Формулировка предусловий позволяет улучшить структуру программы и перехватить неправильное использование функций на ранних этапах программирования. Можно ли использовать эту идею где-нибудь еще? Да, на ум сразу приходит оператор return!
Помимо всего прочего, следует указать, что именно функция будет возвращать; иначе говоря, если мы возвращаем из функции какое-то значение, то
Вернемся к нашей функции, вычисляющей площадь прямоугольника (см. раздел 5.6.1).
// Вычисляет площадь прямоугольника;
// если аргументы неправильные, генерирует исключение Bad_area
int area(int length, int width)
{
if (length<=0 || width <=0) throw Bad_area();
return length*width;
}
Эта функция проверяет предусловия, но они не сформулированы в виде комментариев (для такой короткой функции это вполне допустимо), и считается, что все вычисления проводятся корректно (для таких простых вычислений это также вполне приемлемо). И тем не менее эту функцию можно было написать намного яснее.
int area(int length, int width)
// Вычисляет площадь прямоугольника;
// предусловия: аргументы length и width являются положительными
// постусловия: возвращает положительное значение, являющееся
// площадью
{
if (length<=0 || width <=0) error("area() pre-condition");
int a = length*width;
if (a<=0) error("area() post-condition");
return a;
}
Мы не можем проверить выполнение всех постусловий, но можем проверить их часть, убедившись, что возвращаемое число является положительным.
ПОПРОБУЙТЕ
Найдите пару значений, при которых предусловие выполняется, а постусловие — нет.
Пред- и постусловия обеспечивают проверку логичности кода. Они тесно связаны с понятиями инвариантов (раздел 9.4.3), корректности (разделы 4.2 и 5.2), а также с тестированием (глава 26).
5.11. Тестирование
Как определить, когда следует остановить отладку? Ясно, что отладка должна идти до тех пор, пока не будут выявлены все ошибки, — или нам так покажется. А как узнать, что мы нашли последнюю ошибку? Мы не знаем. Последняя ошибка — это шутка программистов. Такой ошибки не существует. В большой программе никогда невозможно найти последнюю ошибку.
Точка зрения 1. Я умнее любой программы! Я могу взломать код @#$%^!
Точка зрения 2. Я вылизывал эту программу две недели. Она идеальна!