Полезные приемы
Философия проектирования
Общая схема разработки
Разработка снизу вверх: постройте прочный базис, затем применяйте его к специальным случаям.
Бесшовность: применяйте согласованные приемы и инструментарий на этапах анализа, проектирования, разработки и сопровождения.
Обратимость: извлекайте пользу из уроков реализации и корректируйте функциональную спецификацию.
Обобщение: из специализированных классов создавайте повторно используемые классы. Абстрагирование, факторизация - дорога к общности.
Структура систем
Системы создаются только из классов.
Стиль разработки - снизу вверх. Начинайте с того, чем вы располагаете.
Пытайтесь сделать классы с самого начала настолько общими, насколько это возможно.
Пытайтесь сделать классы с самого начала настолько автономными, насколько это возможно.
Два отношения между классами: клиент (с вариантами "ссылочный клиент" и "развернутый клиент"), наследование. Тесное соответствие с отношениями "has" и "is".
Используйте многослойную архитектуру для разделения абстрактного интерфейса и реализации для различных платформ: Vision, WEL/PEL/MEL.
Эволюция системы
Проектируйте с учетом изменений и повторного использования.
При улучшениях проекта вводите понятие устарелых (obsolete) компонентов и классов для облегчения перехода к новой версии.
Классы
Структура класса
Каждый класс должен соответствовать хорошо определенной абстракции данных.
Подход Списка Закупок: если компонент потенциально полезен и согласуется с абстракцией данных, добавьте его.
Классы, предоставляющие льготы: связанная группа полезных свойств (например множество констант).
Активные структуры данных (объекты как абстрактные машины).
Ключевым решением является задание статуса доступа компонентов: закрытых или экспортируемых.
Используйте выборочный экспорт для группы тесно связанных классов: LINKED_LIST, LINKABLE.
Обновление необъектного ПО: инкапсулируйте абстракции в классы (примером является библиотека Math ).
Документация класса
Помещайте в класс настолько много информации, насколько это возможно.
Задавайте заголовочные комментарии тщательно и согласованно; они являются частью официального интерфейса.
Индексируйте классы.
Проектирование компонентов интерфейса
Принцип Разделения Команд и Запросов: функция не должна иметь абстрактного побочного эффекта (конкретный побочный эффект допустим).
В качестве аргументов используйте только операнды.
Установите статус, затем выполняйте операцию.
Для каждой команды, устанавливающей статус, обеспечьте запрос, возвращающий статус.
Для запросов без аргументов внешне не должна быть видима разница в их реализации - атрибутом или функцией.
Допускайте у объектов изменение представления по умолчанию в зависимости от результата запрашиваемой операции (примером является класс комплексных чисел).
Структуры с курсором ( LIST, LINKED_LIST и многие другие).
Использование утверждений
Предусловие связывает клиента, постусловие - поставщика.
Делайте предусловие достаточно сильным, чтобы программа могла хорошо делать свою работу, - но не сильнее.
Два вида предложений инварианта: некоторые предложения идут от лежащей в основе абстракции данных, другие ( инвариант представления ) описывают согласованные свойства реализации. Используйте инвариант, чтобы выразить и улучшить ваше понимание отношений между различными составляющими класса, в частности атрибутами.
Для запросов без аргументов включайте абстрактные свойства в инвариант (даже если для функции свойство появляется в виде постусловия).
При повторном объявлении допустимо ослабление предусловий, позволяющее расширить область применения подпрограммы.
Для достижения эффекта усиления предусловия используйте абстрактные предусловия (основанные на булевых функциях) в оригинале.
Даже и без необходимости усиления абстрактные предусловия являются предпочтительными.
Любое предусловие должно обеспечиваться и проверяться клиентом перед вызовом компонента.
Не усердствуйте в усилении постусловий - оставьте возможность их усиления потомками (например, можно оставить одностороннюю импликацию implies вместо эквивалентности).
Как обращаться со специальными ситуациями
Априорная проверка: до выполнения операции проверяйте возможность ее применения.
Апостериорная проверка: выполните операцию, затем запросите атрибут для выяснения того, как она сработала.
Когда все рушится, используйте обработку исключений.
Организованный отказ: если в конце выполняется предложение rescue, не забудьте восстановить инвариант. Вызывающая программа получит также исключение.
Повторение выполнения: испробуйте другой алгоритм или (стратегия надежды) тот же повторно. Сохраните информацию в атрибутах или локальных сущностях, инициализируемых в момент вызова, но не при повторах retry.