Читаем Программист-прагматик. Путь от подмастерья к мастеру полностью

Рассмотрим программу, которая считывает с устройства ввода номер, извлекает из него квадратный корень (вызывая функцию sqrt) и выводит результат на печать. Функция sqrt имеет предусловие – ее аргумент не должен быть отрицательным числом. Если пользователь вводит отрицательное число, то именно вызывающая программа должна гарантировать, что это число не будет передано функции sqrt. Вызывающая программа может воспользоваться многими вариантами: она может завершить работу, выдать предупреждение и начать считывать другое число, она также может преобразовать число в положительное и добавить к результату, выданному функцией Sqrt, мнимую единицу. Какой бы вариант ни использовался, эта проблема определенно не связана с функцией sqrt.

Выражая область значений функции извлечения квадратного корня в предусловии подпрограммы sqrt, вы перекладываете ответственность за правильность на вызывающую программу, которой она принадлежит. Затем вы можете спокойно продолжать разработку подпрограммы sqrt, зная, что ее входные параметры не выйдут за пределы соответствующей области.


Если ваш алгоритм извлечения квадратного корня не работает (или выходит за пределы погрешности), вы получите сообщение об ошибке и трассировку стека, указывающую на цепочку вызовов.

Если вы передаете sqrt отрицательный параметр, рабочая среда Eiffel выводит на печать ошибку "sqrt_argjnust_be_positive" (аргумент функции sqrt должен быть положительным) наряду с трассировкой стека. Этот вариант реализован лучше, чем его аналогия в языках типа Java, С, и С++, где при передаче отрицательного числа в sqrt выдается специальное значение NaN (Not a Number – не число). Далее по ходу программы, когда вы попытаетесь произвести со значением NaN некие математические действия, результаты этого будут поистине удивительными.

Проблему намного проще найти и диагностировать "не сходя с места", при аварийном завершении работы программы.

Другие случаи применения инвариантов

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

Инварианты цикла

Понимание граничных условий для нетривиального цикла может оказаться проблематичным. Циклы испытывают воздействие "проблемы банана" (я знаю, как записать по буквам слово «банан», но не знаю, в какой момент нужно остановиться), ошибки "постов охраны" (путаница в том, что подсчитывать: сами посты или интервалы между ними) и вездесущей ошибки завышения (занижения) [URL 52].

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

int m = arr[0]; // пример предполагает, что длина массива > 0

int i = 1;

// Инвариант цикла: m = max(arr[0:i-1])

while (i < arr.length) {

    m = Math.max(m, arr[i]);

    i = i + 1;

}

(arr [m:n] – принятое обозначение фрагмента массива, элементы которого имеют индексы от m до n). Инвариант должен быть истинным до начала выполнения цикла, а тело цикла должно гарантировать, что инвариант будет оставаться истинным во время выполнения цикла. Таким образом, нам известно, что инвариант истинен после выполнения цикла, и следовательно наш результат является достоверным. Инварианты цикла могут быть запрограммированы в явном виде (как утверждения); они также полезны при проектировании и документировании.

Семантические инварианты

Вы можете использовать семантические инварианты для выражения неизменных требований при составлении своего рода "философского контракта".

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

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

Но убедитесь в том, что вы не смешиваете требования, представляющие собой жесткие, неизменные законы с теми, что являются не более чем политикой, которая может измениться вместе с правящим режимом. Именно поэтому мы используем термин "семантические инварианты" – он должен занимать главенствующее место при определении сути предмета и не подчиняться прихотям политики (для которой предназначаются более динамичные правила ведения бизнеса).

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
Программирование. Принципы и практика использования C++ Исправленное издание
Программирование. Принципы и практика использования C++ Исправленное издание

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка. Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие. Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток. Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова

Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT
Встраиваемые системы. Проектирование приложений на микроконтроллерах семейства 68HC12/HCS12 с применением языка С
Встраиваемые системы. Проектирование приложений на микроконтроллерах семейства 68HC12/HCS12 с применением языка С

В книге последовательно рассматриваются все этапы создания встраиваемых систем на микроконтроллерах с применением современных технологий проектирования. Задумав эту книгу, авторы поставили перед собой задачу научить читателя искусству создания реальных устройств управления на однокристальных микроконтроллерах. Издание содержит материал, охватывающий все вопросы проектирования, включает множество заданий для самостоятельной работы, примеры программирования, примеры аппаратных решений и эксперименты по исследованию работы различных подсистем микроконтроллеров. Данная книга является прекрасным учебным пособием для студентов старших курсов технических университетов, которые предполагают связать свою профессиональную деятельность с проектированием и внедрением встраиваемых микропроцессорных систем. Книга также будет полезна разработчикам радиоэлектронной аппаратуры на микроконтроллерах.

Дэниэл Дж. Пак , Стивен Ф. Барретт

Программирование, программы, базы данных / Компьютерное «железо» / Программирование / Книги по IT