no_error_if_possible: (not (old empty)) = (error = 0)

end

feature -- Status report (Отчет о статусе)

empty: BOOLEAN is

-- Пуст ли стек?

do

Result := (capacity = 0) or else representation.empty

end

error: INTEGER

-- Индикатор ошибки, устанавливаемый различными компонентами

-- в ненулевое значение, если они не могут выполнить свою работу

full: BOOLEAN is

-- Заполнен ли стек?

do

Result := (capacity = 0) or else representation.full

end

Overflow, Underflow, Negative_size: INTEGER is unique

-- Возможные коды ошибок

feature -- Element change (Изменение элементов)

put (x: G) is

-- Добавить x на вершину, если возможно; иначе задать код ошибки.

-- Без всяких предусловий!

do

if full then

error := Overflow

else

check representation /= Void end

representation.put (x); error := 0

end

ensure

error_code_if_impossible: (old full) = (error = Overflow)

no_error_if_possible: (not old full) = (error = 0)

not_empty_if_no_error: (error = 0) implies not empty

added_to_top_if_no_error: (error = 0) implies item = x

one_more_item_if_no_error: (error = 0) implies count = old count + 1

end

remove is

-- Удалить вершину, если возможно; иначе задать код ошибки.

-- Без всяких предусловий!

do

if empty then

error := Underflow

else

check representation /= Void end

representation.remove

error := 0

end

ensure

error_code_if_impossible: (old empty) = (error = Underflow)

no_error_if_possible: (not old empty) = (error = 0)

not_full_if_no_error: (error = 0) implies not full

one_fewer_item_if_no_error: (error = 0) implies count = old count - 1

end

feature {NONE} - Implementation (Реализация)

representation: STACK2 [G]

-- Незащищенный стек используется для реализации

capacity: INTEGER

-- Максимальное число элементов стека

end - class STACK3

Операции этого класса не имеют предусловий (более точно, имеют True в качестве предусловия). Результат выполнения может характеризовать ненормальную ситуацию, постусловие переопределено так, чтобы позволить отличать корректную и ошибочную обработку. Например, при вызове s.remove, где s это экземпляр класса STACK3, в корректной ситуации значение s.error будет равно 0; в ошибочной - Underflow. В последнем случае никакая другая работа выполняться не будет. Клиент несет ответственность за проверку s.error после вызова. Как уже отмечалось, у общецелевого модуля, такого как STACK3 нет способа решить, что делать в ошибочной ситуации: выдать сообщение об ошибке, произвести корректировку ситуации...

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

Несколько технических замечаний к приведенному примеру класса.

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

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