Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4087 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Лекция 5:

Принципы проектирования класса

Ключевые концепции

  • Класс должен быть известен своим интерфейсом, специфицируя предлагаемые службы независимо от их реализации.
  • Разработчики класса должны стараться предоставить простые согласованные интерфейсы.
  • Одна из ключевых проблем при проектировании класса состоит в правильном разделении экспортируемых и закрытых компонентов.
  • Проектирование повторно используемых модулей не является первоочередной задачей - интерфейс должен стабилизироваться после некоторого периода использования. Если этого не происходит, то это свидетельствует об изъяне в проекте. Механизм устаревших классов и компонентов делает возможным сгладить переход к лучшей версии проекта.
  • Зачастую полезно рассматривать некоторые структуры данных как активные машины с внутренним состоянием, запоминаемым между вызовами компонентов.
  • Правильное использование утверждений - предусловий, постусловий, инвариантов - является основой документирования интерфейсов.
  • Для разбора особых случаев лучше применять стандартные управляющие структуры, применяя либо априорную, либо апостериорную схему. Механизм дисциплинированных исключений остается необходимым в тех случаях, когда выполнение должно быть прервано из-за потенциальных угроз, связанных с некорректным выполнением операции.

Библиографические замечания

В работах Парнаса ([Parnas 1972], [Parnas 1972a]) вводится много похожих идей по проектированию интерфейса.

Различение операндов и опций и результирующий принцип взяты из работы [M1982a].

Понятие активной структуры данных поддерживается в некоторых языках программирования управляющими абстракциями, называемыми итераторами. Итератор представляет механизм, определенный совместно со структурой данных, описывающий, как применять некую операцию к каждому элементу структуры. Например, итератор, ассоциированный со списком, описывает циклический механизм прохода по списку, применяя данную операцию к каждому элементу списка, итератор дерева задает некую стратегию обхода дерева. В работах [Liskov 1981], [Liskov 1986] содержится подробное обсуждение концепции итераторов, доступных в языке программирования CLU. В объектной технологии итераторы могут быть определены в классах, не встраивая их в виде конструкций языка программирования [M 1994a].

Пример адаптивной реализации комплексных чисел взят из [M1979], где он описан на Simula.

Грамотное программирование (Literate programming) [Knuth 1984] утверждает, как и данная лекция, что программы должны содержать свою документацию. Его концепции, однако, существенно отличаются от концепций объектной технологии. Одно из упражнений предлагает сравнить два подхода.

Статьи Джеймса Мак-Кима и Ричарда Билака [Bielak 1993], [McKim 1992a] дают полезные советы по проектированию интерфейса, основанные на понятии Проектирования по Контракту.

Упражнения

У5.1 Функция с побочным эффектом

Пример управления памятью на уровне компонентов (см. лекцию 9 курса "Основы объектно-ориентированного программирования") для связных списков имеет функцию fresh, вызывающую процедуру remove для стеков, следовательно, имеющую побочный эффект. Обсудите, является ли это приемлемым.

У5.2 Операнды и опции

Исследуйте класс или доступную библиотеку и определите, какие аргументы подпрограмм являются операндами и какие - опциями.

У5.3 Возможные аргументы

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

У5.4 Число элементов как функция

Адаптируйте определение класса LINKED_LIST [G] так, чтобы count стал функцией, а не атрибутом, оставив неизменным интерфейс класса.

У5.5 Поиск в связных списках

Напишите процедуру search (x: G) для класса LINKED_LIST, разыскивающую следующее вхождение x.

У5.6 Теоремы в инварианте

Докажите истинность трех утверждений из первой части инварианта класса LINKED_LIST, отмеченных как теоремы (см. "Принципы проектирования класса" ).

У5.7 Двунаправленные списки

Напишите класс, задающий двунаправленные списки с интерфейсом LINKED_LIST, но более эффективной реализацией таких операций, как back, go и finish.

У5.8 Альтернативный проект связного списка

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

У5.9 Вставка в связный список

Глядя на remove, напишите процедуры put_left и put_right для вставки элементов слева и справа от позиции курсора.

У5.10 Циклические списки

Объясните, почему класс LINKED_LIST не может использоваться для циклических списков. (Подсказка: покажите, что утверждения будут нарушаться.) Напишите класс CIRCULAR_LINKED, реализующий циклические списки.

У5.11 Функции ввода, свободные от побочных эффектов

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

У5.12 Документация

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

У5.13 Самодокументированное ПО

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