Чтение онлайн

ЖАНРЫ

Основы объектно-ориентированного программирования

Мейер Бертран

Шрифт:
Есть сходство в данном обсуждении и обсуждении использования частичных функций в математических моделях, рассматриваемое в лекции про АТД. Там говорилось, что целесообразнее использовать частичные функции, чем делать функцию всюду определенной, введением специального неопределенного значения - ωinteger. Эти две идеи близки, Проектирование по контракту является частью применения к программным конструкциям концепции частичных функций, замечательно гибкого и мощного аппарата формальных спецификаций.

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

Принцип обоснованности предусловия

Каждое предусловие программы при требовательном стиле проектирования должно удовлетворять следующим требованиям:

1 Предусловие появляется в официальной документации, поставляемой авторам клиентских модулей.

2 Предусловие формулируется только в терминах спецификации, что делает возможным его вычисление.

Первое требование поддерживается понятием краткой формы, изучаемой позднее в этой лекции. Второе требование исключает появление ограничений, определяемых реализацией поставщика программы. Например, для программы, занимающейся выталкиванием элементов из стека, предусловие not empty является требованием, проверяемым в терминах спецификации, и вытекающим из очевидного факта - из пустого стека ничего нельзя вытолкнуть. При вычислении квадратного корня предусловие x>0 отражает известный математический факт, - отрицательные числа не имеют вещественных квадратных корней.

Некоторые ограничения могут навязываться реализацией. Например, в программе put из класса STACK2 присутствие в качестве предусловия require not full связано с реализацией стека на основе массива. Но это не является нарушением принципа, поскольку класс STACK2 в полном соответствии с его спецификацией определяет стеки ограниченной емкости, что отражено, например, в предложении indexing этого класса. АТД, служащий в роли спецификации этого класса, не задает наиболее общий вид стеков, но является понятием стека ограниченной емкости.

Обычно следует избегать структур ограниченной емкости; даже в случае массивов можно строить стек на динамических массивах, изменяющих размерность при необходимости. В Базовой библиотеке представлен общий класс, описывающий стеки 11.1) , отличающийся от класса STACK2 тем, что в нем не используется понятие емкости; стек по умолчанию перестраивается, когда текущей емкости недостаточно для хранения очередного поступающего элемента.

общий класс, описывающий стекиобщий класс, описывающий стеки 11.1

Предусловия и статус экспорта

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

Рассмотрим следующую ситуацию:

– - Предупреждение: это неправильный класс, только в целях иллюстрации.

class SNEAKY feature

tricky is

require

accredited

do

...

end

feature {NONE}

accredited: BOOLEAN is do ... end

end

Спецификация для tricky устанавливает, что любой вызов этой процедуры должен удовлетворять условию, выраженному булевой функцией accredited. Но при экспорте класса эта функция для клиентов является закрытой, поэтому у них нет способа проверить выполнимость условия перед вызовом tricky. Очевидно, подобная ситуация неприемлема.

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

Это правило учитывает все возможные ситуации экспорта, а не только случаи доступности всем клиентам (tricky) или полной недоступности (accredited). Как отмечалось, при обсуждении проблемы скрытия информации, компонент класса можно сделать доступным для некоторых клиентов, явно перечислив их в feature предложении, например feature {A, B, ... }, определяющего доступность только для классов A, B, ... и их потомков. Сформулируем правило языка:

Правило Доступности предусловия

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

В соответствии с этим правилом каждый клиент, способный вызвать программу, способен проверить ее предусловие. По этому правилу класс SNEAKY является коварным, некорректно построенным, поскольку экспортирует tricky с недоступным предусловием. Нетрудно превратить этот класс в правильно построенный, изменив статус экспорта у accredited. Если tricky появится с предложением feature в форме feature {A, B, C}, то accredited должна экспортироваться, по меньшей мере, клиентам A, B, C, появляясь в той же группе feature, что и tricky. Можно задать для accredited собственное feature– предложение в одной из форм: feature {A, B, C}, feature {A, B, C, D, ...} или просто feature. Любое нарушение этого правила приведет к ошибке в период компиляции. Класс SNEAKY, например, будет забракован компилятором.

Подобного правила нет для постусловий. Не является ошибкой в постусловии ссылаться на компоненты, закрытые или экспортируемые избранным клиентам. Просто это означает, что описание эффекта выполнения программы содержит некоторые свойства, непосредственно не используемые клиентом. Подобная ситуация имеет место в процедуре put класса STACK2:

put (x: G) is

– - Добавить элемент x на вершину

require

not full

do

...

ensure

... Другие предложения...

in_top_array_entry: representation @ count = x

end

Последнее предложение в постусловии устанавливает, что элемент массива с индексом count содержит последний втолкнутый в стек элемент. Это свойство реализации, хотя put обычно доступно (экспортируется всем клиентам), массив representation является закрытым. Но ничего ошибочного в постусловии нет. Оно просто включает наряду со свойствами, полезными для клиентов ("Другие предложения"), свойство, имеющее смысл только для тех, кто знаком с полным текстом класса. Такие закрытые предложения не будут появляться в краткой форме класса - документации, предназначенной для авторов клиентских модулей.

Поделиться с друзьями: