Объектно-ориентированное проектирование с примерами

         

Измерение качества абстракции


По мнению Ингалса "для построения системы должен использоваться минимальный набор неизменяемых компонент; сами компоненты должны быть по возможности стандартизованы и рассматриваться в рамках единой модели" [51]. Применительно к объектно-ориентированному проектированию такими компонентами являются классы и объекты, отражающие ключевые абстракции системы, а единство обеспечивается соответствующими механизмами реализации.

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

    зацепление;

    связность;

    достаточность;

    полнота;

    примитивность.

    Термин зацепление взят из структурного проектирования, но в более вольном толковании он используется и в объектно-ориентированном проектировании. Стивенс, Майерс и Константайн определяют зацепление как "степень глубины связей между отдельными модулями. Систему с сильной зависимостью между модулями гораздо сложнее воспринимать и модифицировать. Сложность системы может быть уменьшена путем уменьшения зацепления между отдельными модулями" [52]. Пример неправильного подхода к проблеме зацепления привел Пейдж-Джонс, описав модульную стереосистему, в которой источник питания размещен в одной из звуковых колонок [53].

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

    Понятие связности также заимствовано из структурного проектирования. Связность - это степень взаимодействия между элементами отдельного модуля (а для OOD еще и отдельного класса или объекта), характеристика его насыщенности. Наименее желательной является связность по случайному принципу, когда в одном классе или модуле собираются совершенно независимые абстракции. Для примера можно вообразить класс, соединяющий абстракции собак и космических аппаратов. Наиболее желательной является функциональная связность, при которой все элементы класса или модуля тесно взаимодействуют в достижении определенной цели. Так, например, класс Dog будет функционально связным, если он описывает поведение собаки, всей собаки, и ничего, кроме собаки.

    К идеям зацепления и связности тесно примыкают понятия достаточности, полноты и примитивности. Под достаточностью подразумевается наличие в классе или модуле всего необходимого для реализации логичного и эффективного поведения. Иначе говоря, компоненты должны быть полностью пригодны к использованию. Для примера рассмотрим класс set (множество). Операция удаления элемента из множества в этом классе, очевидно, необходима, но будет ошибкой не включить в этот класс и операцию добавления элемента. Нарушение требования достаточности обнаруживается очень быстро, как только создается клиент, использующий абстракцию. Под полнотой подразумевается наличие в интерфейсной части класса всех характеристик абстракции. Идея достаточности предъявляет к интерфейсу минимальные требования, а идея полноты охватывает все аспекты абстракции. Полнотой характеризуется такой класс или модуль, интерфейс которого гарантирует все для взаимодействия с пользователями. Полнота является субъективным фактором, и разработчики часто ею злоупотребляют, вынося на верх такие операции, которые можно реализовать на более низком уровне.Из этого вытекает требование примитивности. Примитивными являются только такие операции, которые требуют доступа к внутренней реализации абстракции. Так, в примере с классом set операция Add (добавление к множеству элемента) примитивна, а операция добавления четырех элементов не будет примитивной, так как вполне эффективно реализуется через операцию добавления одного элемента. Конечно, эффективность тоже вещь субъективная. Операция, которая требует прямого доступа к структуре данных, примитивна по определению. Операция, которая может быть описана в терминах существующих примитивных операций, но ценой значительно больших вычислительных затрат, также является кандидатом на включение в разряд примитивных [Примером может служить операция добавления к множеству произвольного числа элементов (а не обязательно четырех). - Примеч. ред.].


    Содержание раздела