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

Полезные приемы

< Лекция 6 || Лекция 7: 12 || Лекция 8 >
Аннотация: Примеры ОО-проектирования, приведенные в предыдущих лекциях, иллюстрируют несколько характерных приемов. Хотя мы и не закончили наш обзор методологических проблем - нам предстоит еще рассмотрение правил стиля, концепций ОО-анализа, вопросов обучения, процессов ПО, - сделаем паузу и кратко сформулируем то, что уже изучено. Это будет самая короткая лекция во всей книге. Она просто перечисляет плодотворные идеи, объединяя их в группы с предваряемыми ключевыми словами, напоминая о тех примерах, где мы впервые столкнулись с этими идеями.

Философия проектирования

Общая схема разработки

Разработка снизу вверх: постройте прочный базис, затем применяйте его к специальным случаям.

Бесшовность: применяйте согласованные приемы и инструментарий на этапах анализа, проектирования, разработки и сопровождения.

Обратимость: извлекайте пользу из уроков реализации и корректируйте функциональную спецификацию.

Обобщение: из специализированных классов создавайте повторно используемые классы. Абстрагирование, факторизация - дорога к общности.

Структура систем

Системы создаются только из классов.

Стиль разработки - снизу вверх. Начинайте с того, чем вы располагаете.

Пытайтесь сделать классы с самого начала настолько общими, насколько это возможно.

Пытайтесь сделать классы с самого начала настолько автономными, насколько это возможно.

Два отношения между классами: клиент (с вариантами "ссылочный клиент" и "развернутый клиент"), наследование. Тесное соответствие с отношениями "has" и "is".

Используйте многослойную архитектуру для разделения абстрактного интерфейса и реализации для различных платформ: Vision, WEL/PEL/MEL.

Эволюция системы

Проектируйте с учетом изменений и повторного использования.

При улучшениях проекта вводите понятие устарелых (obsolete) компонентов и классов для облегчения перехода к новой версии.

Классы

Структура класса

Каждый класс должен соответствовать хорошо определенной абстракции данных.

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

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

Активные структуры данных (объекты как абстрактные машины).

Ключевым решением является задание статуса доступа компонентов: закрытых или экспортируемых.

Используйте выборочный экспорт для группы тесно связанных классов: LINKED_LIST, LINKABLE.

Обновление необъектного ПО: инкапсулируйте абстракции в классы (примером является библиотека Math ).

Документация класса

Помещайте в класс настолько много информации, насколько это возможно.

Задавайте заголовочные комментарии тщательно и согласованно; они являются частью официального интерфейса.

Индексируйте классы.

Проектирование компонентов интерфейса

Принцип Разделения Команд и Запросов: функция не должна иметь абстрактного побочного эффекта (конкретный побочный эффект допустим).

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

Установите статус, затем выполняйте операцию.

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

Для запросов без аргументов внешне не должна быть видима разница в их реализации - атрибутом или функцией.

Допускайте у объектов изменение представления по умолчанию в зависимости от результата запрашиваемой операции (примером является класс комплексных чисел).

Структуры с курсором ( LIST, LINKED_LIST и многие другие).

Использование утверждений

Предусловие связывает клиента, постусловие - поставщика.

Делайте предусловие достаточно сильным, чтобы программа могла хорошо делать свою работу, - но не сильнее.

Два вида предложений инварианта: некоторые предложения идут от лежащей в основе абстракции данных, другие ( инвариант представления ) описывают согласованные свойства реализации. Используйте инвариант, чтобы выразить и улучшить ваше понимание отношений между различными составляющими класса, в частности атрибутами.

Для запросов без аргументов включайте абстрактные свойства в инвариант (даже если для функции свойство появляется в виде постусловия).

При повторном объявлении допустимо ослабление предусловий, позволяющее расширить область применения подпрограммы.

Для достижения эффекта усиления предусловия используйте абстрактные предусловия (основанные на булевых функциях) в оригинале.

Даже и без необходимости усиления абстрактные предусловия являются предпочтительными.

Любое предусловие должно обеспечиваться и проверяться клиентом перед вызовом компонента.

Не усердствуйте в усилении постусловий - оставьте возможность их усиления потомками (например, можно оставить одностороннюю импликацию implies вместо эквивалентности).

Как обращаться со специальными ситуациями

Априорная проверка: до выполнения операции проверяйте возможность ее применения.

Апостериорная проверка: выполните операцию, затем запросите атрибут для выяснения того, как она сработала.

Когда все рушится, используйте обработку исключений.

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

Повторение выполнения: испробуйте другой алгоритм или (стратегия надежды) тот же повторно. Сохраните информацию в атрибутах или локальных сущностях, инициализируемых в момент вызова, но не при повторах retry.

< Лекция 6 || Лекция 7: 12 || Лекция 8 >