Назад Оглавление Вперед




8. Стиль разработки объектно-ориентированных проектов

8.1 Общие правила оформления классов

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

8.1.1 Составление атрибутов

    Атрибуты класса должны быть связаны с базовыми свойствами этого класса в предметной области и не должны быть связаны с конкретной задачей или методом реализации этой задачи. Не рекомендуется использовать атрибуты, предназначенные для хранения временных переменных, или являющиеся просто заменителем описания локальных переменных в методах. Так, например, для класса ⌠матрица■ нельзя вводить атрибуты i, j, которые предназначены для того, что бы не описывать локальные переменные i и j в реализации каждого метода. Лишние атрибуты резко ухудшают читабельность программ и являются дополнительным источником ошибок.

8.1.2 Необходимое и достаточное количество свойств

    Каждый класс должен содержать необходимое и достаточное количество свойств ( атрибутов и методов поведения ). Нужно избегать слишком слабого или слишком детального определения классов. Наиболее типичный класс должен включать не более 10 атрибутов и не более 10 методов поведения. При превышении этого количества стоит подумать о создании нового класса. Недостаточное количество свойств приведет к необходимости добавления их во всех производных класса, что замедлит повторное использование класса. Избыточность свойств приведет к тяжеловесности программы при выполнении и чтении.

8.1.3 Конструкторы

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

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

8.1.4 Независимость от системных библиотек и реализации

    Базовые классы не должны использовать операции ввода или вывода. Это связано с тем, что базовые классы часто будут использоваться, а это в свою очередь приводит к выводу о том, что данные для них часто будут формироваться с помощью других программ, а не вводиться пользователем. Если в методе ⌠вставить■ для хэш-таблицы будет использоваться ввод с клавиатуры для получения значения ключа, то такую таблицу невозможно будет использовать в компиляторе. Аналогичная ситуация сложится, если этот же метод после вставки выдаст на экран сообщение вида ⌠вставка успешно завершена■.

8.2 Наследование

    Наследование разделяется на две важные части:

8.2.1 Наследование атрибутов

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

    Рис. 8.1. пример наследования атрибутов.

и пусть необходимо для каждой фигуры добавить атрибут ⌠цвет заполнения внутренней области■. Наследование позволяет очень легко модифицировать группу структур данных за одну операцию. Но это можно сделать двумя способами: во-первых, можно ввести новый атрибут ⌠цвет■ в класс ⌠геометрическая фигура■ и по наследованию этот атрибут получат все новые фигуры, во-вторых, можно ввести новый класс ⌠цветная фигура■, как наследника от ⌠геометрической фигуры■. Посмотрим на различия этих двух вариантов:

новый класс увеличивает количество классов и следовательно сложность проекта,

точка изгиба в многоугольнике не должна иметь цвет.

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

8.2.2 Наследование методов поведения

    Наследование методов поведения представляет собой возможность для производного класса

методов поведения базового класса.

    Использование можно продемонстрировать не примере метода ⌠переместить■ класса ⌠геометрическая фигура■. Производные классы ⌠прямоугольник■ и ⌠окружность■ не имеют собственного метода ⌠переместить, но могут им пользоваться. Этот метод не использует специфических свойств ⌠прямоугольника■ и ⌠окружности■.

    Метод ⌠нарисовать■ класса ⌠прямоугольник■ полностью переопределяет поведение базового класса.

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

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

8.3 Необходимые и достаточные свойства классов

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

    Рис. 8.2. Классы геометрических фигур. Вариант с недостаточностью.

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

    Другой подход заключается в том, чтобы размер охватывающего прямоугольника хранить в геометрической фигуре. Это ликвидирует все указанные недостатки. Единственный недостаток будет заключаться в том, что такие фигуры как ⌠окружность■ и ⌠квадрат■ будут иметь один из атрибутов всегда равный другому ( размеры по X и Y ).

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

    Но не следует нагружать базовые класса и слишком большим набором атрибутов и методов поведения для того, что бы производные объекты не были слишком громоздкими. Самое важное, что нужно помнить, что класс создается не для решения конкретной задачи, а для описания некоторой категории предметной области. Типичным примером избыточности является метод ⌠показать■ для хэш-таблицы, который выводит информацию на экран монитора с помощью оператора write, или метод ⌠вставить■, который запрашивает ключ элемента для ввода с клавиатуры. Когда данная хэш-таблица будет использоваться в среде MS Windows, то окажется, что эти методы не нужны.

8.4 Наследование и использование

    Как было указано выше существует два основных отношения между классами: отношение наследования и отношение включения. Как правило эти отношения четко отличаются друг от друга и у разработчика не возникает проблем с выбором одного из отношений для конкретных классов. Например, очевидно, что ⌠прямоугольник■ является ⌠геометрической фигурой■, а ⌠многоугольник■ является ⌠геометрической фигурой■ и включает ⌠точки■ для хранения координат углов.

    Иногда сделать выбор между наследованием и включением не так просто. Рассмотрим два варианта определения класса хэш-таблицы.

а)                                                                            б)

    Рис 8.3. Варианты определения класса хэш-таблицы для наследования и включения.

    Вариант а) предполагает наследование свойств коллекции в хэш-таблице, вариант б) предполагает, что хэш-таблица имеет атрибут ⌠элементы■ типа коллекция.

Назад Оглавление Вперед