- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы объектно-ориентированного программирования - Бертран Мейер
Шрифт:
Интервал:
Закладка:
end
ensure
error_code_if_impossible: (old empty) = (error = Underflow)
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 нет способа решить, что делать в ошибочной ситуации: выдать сообщение об ошибке, произвести корректировку ситуации...
Такие модули фильтры служат для отделения нормальных ситуаций от ситуаций, обрабатывающих ошибки. В этом отличие корректности от устойчивости, объясняемое в начале книги: написание модуля корректно выполняющего свою задачу в предусмотренных случаях - одна задача, сделать так, чтобы и в непредусмотренных ситуациях обработка выполнялась сносно - совсем другая задача. Обе они необходимы, но их нужно разделять и управлять ими по-разному. Одна из типичных ошибок, приводящая к безнадежной сложности программных систем, - в алгоритм, делающий действительно нечто полезное, добавляется куча проверок на безнадежные ситуации и из лучших побуждений делается попытка управлять ими. В таких системах путаница начинает расти как грибы после дождя.
Несколько технических замечаний к приведенному примеру класса.
[x]. Экземпляр STACK3 - содержит атрибут representation, представляющий ссылку на экземпляр STACK2, содержащий, в свою очередь, ссылку на массив. Эти обходные пути пагубно отражаются на эффективности, избежать этого можно введением наследования, изучаемого в последующих лекциях.
[x]. Булева операция or else подобна or, но если первый операнд равен True, игнорирует второй операнд, возможно неопределенный в такой ситуации.
[x]. Инструкция check, используемая в put и remove, служит для проверки выполнения некоторых утверждений. Она будет изучаться позднее в этой лекции.
В заключение: вы, наверное, отметили тяжеловесность STACK3 в сравнении с простотой STACK2, достигнутой благодаря предусловиям. Это хороший пример, показывающий, что толерантный стиль может приводить к бесполезно усложненному ПО. Требовательный стиль, по контрасту, вытекает из общего духа Проектирования по контракту. Попытка управлять всем, - и возможными и невозможными случаями - совсем не лучший способ помочь вашим клиентам. Если вместо этого вы построите классы, влекущие возможно более строгие условия на их использование, точно опишите эти условия, включив их в документацию класса, вы реально облегчите жизнь вашим клиентам. Требовательная любовь (tough love) может быть лучше всепрощающей; лучше эффективная поддержка функциональности с проверяемыми ограничениями, чем страстная попытка предугадать желания клиентов, принятие возможно неадекватных решений, жертвой чего становятся простота и эффективность.
Для модулей, чьими клиентами являются другие программные модули, требовательный подход обычно является правильным выбором. Возможным исключением становятся модули, предназначенные для клиентов, чьи авторы используют не ОО-языки и могут не понимать основных концепций Проектирования по контракту.
Толерантный подход остается полезным для модулей, принимающих данные от внешнего мира. Как отмечалось, в этом случае строятся фильтры, отделяющие внешний мир от обрабатывающих модулей. Класс STACK3 иллюстрирует идеи построения подобных фильтров.Инварианты класса
Предусловия и постусловия описывают свойства отдельных программ. Но экземпляры класса обладают также глобальными свойствами. Их принято называть инвариантами класса (class invariants), и они определяют более глубокие семантические свойства и ограничения целостности, характеризующие класс.
Определение и пример
Рассмотрим снова реализацию стека классом STACK2:
class STACK2 [G] creation
make
feature
? make, empty, full, item, put, remove?
capacity: INTEGER
count: INTEGER
feature {NONE} -- Implementation
representation: ARRAY [G]
end
Атрибуты класса - массив representation и целые capacity, count - задают представление стека. Хотя предусловия и постусловия программ отражают семантику стека, их недостаточно для выражения важных свойств, связывающих атрибуты. Например, count всегда должно удовлетворять условию:
0 <= count; count <= capacity
из которого следует, что capacity >=0 и что capacity задает размер массива:
capacity = representation.capacity
Инвариант класса это утверждение, выражающее общие согласованные ограничения, применимые к каждому экземпляру класса как целому. Этим они отличаются от предусловий и постусловий, характеризующих отдельные программы.
Выше приведенные примеры инвариантов включали только атрибуты. Инварианты могут выражать отношения между функциями и между функциями и атрибутами. Например, инвариант STACK2 может включать следующее свойство, описывающее связь между функцией empty и count:
empty = (count = 0)
Этот пример не показателен, он повторяет утверждение, заданное постусловием empty. Более полезные утверждения те, которые включают только атрибуты или более чем одну функцию.
Вот еще один типичный пример. Предположим, что мы имеем дело с банковскими счетами, и есть класс Bank_Account с компонентами: deposits_list, withdrawals_list и balance. Тогда инвариантом такого класса может быть утверждение в форме:
consistent_balance: deposits_list.total - withdrawals_list.total = balance
где функция total дает суммарное значение списка всех операций (приходных или расходных). Инвариант определяет основное условие согласования всех банковских операций над счетом, связывая баланс, приходные и расходные операции.
Форма и свойства инвариантов класса
Синтаксически инвариант класса является утверждением, появляющимся в предложении invariant, стоящим после всех предложений feature, и перед предложением end. Вот пример:
