Ясно, чем мы рискуем: появление функций в выражениях означает введение потенциально императивных элементов (программ) в чисто аппликативный, до сего времени, мир утверждений. Без функций мы имели ясное и четкое разделение ролей, обсуждаемое ранее: инструкции предписывают, утверждения описывают. Теперь мы открыли ворота аппликативного города императивным полчищам.
Все же трудно сопротивляться мощи использования функций, поскольку все альтернативы имеют свои недостатки.
[x]. Включение полного языка спецификаций, как отмечалось, приводит к потере эффективности и простоты изучения.
[x]. Вероятно, хуже то, что неясно, достаточны ли общепринятые языки утверждений. Возьмем, например, такого естественного кандидата, в которого многие верят, - язык логики предикатов первого порядка. Этот формализм не позволяет нам выразить некоторые свойства, представляющие непосредственный интерес для разработчиков и часто используемые в утверждениях, такие как, например, "граф не имеет циклов" (типичный инвариант цикла). Математически это может быть выражено как
Все это создает больше трудностей для программиста, которому проще написать булеву функцию
Но остается необходимость разделять императивные и аппликативные элементы. Любая программно реализованная функция, используемая в утверждениях для специфицирования свойств, должна быть "безупречной", без обвинений ее в императивности, - она не должна быть причиной никаких изменений абстрактного состояния.
Это неформальное требование достаточно ясно на практике; формализм подъязыка IFL исключает все императивные элементы, которые либо изменяют глобальное состояние системы, либо не имеют тривиальных аппликативных эквивалентов, в частности исключаются:
[x]. присваивания атрибутам;
[x]. присваивания в циклах;
[x]. вызовы программ, не входящих в IFL.
Если особо тщательно дирижировать функциями, достаточно простыми с очевидной корректностью, то использование в утверждениях программно реализованных функций дает мощный метод абстракции.
Некоторые технические вопросы могут потребовать внимания. Функция
Правило вычисления утверждения
В процессе вычисления утверждений, входящие в них вызовы программ должны выполняться без вычисления ассоциированных утверждений.
Если вызов
Рассматривайте
Инварианты класса и семантика ссылок
ОО-модель, разрабатываемая до сих пор, включала два частично не связанных аспекта, оба из которых полезны:
[x]. Понятие инварианта класса, введенное в этой лекции.
[x]. Гибкая модель периода выполнения, детально рассмотренная в начальных лекциях, существенно использующая ссылки.
К несчастью, эти индивидуально желательные свойства могут стать причиной трудностей при их совместном использовании.
Проблема вновь в динамически создаваемых псевдонимах, предохраняющих нас от проверки корректности класса на том основании, что класс делает это сам. Мы уже видели, что корректность класса означает проверку
1 Каждая из
2 Каждая из