Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений на С++, страница 15
Описание файла
PDF-файл из архива "Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений на С++", который расположен в категории "". Всё это находится в предмете "объектно-ориентированный анализ и проектирование" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 15 страницы из PDF
Все структуры данных должны быть обособлены в модуле; доступ к нимбудет возможен для всех процедур этого модуля и закрыт для всех других. Доступ к данным измодуля должен осуществляться только через процедуры данного модуля» [62]. Другими словами,следует стремиться построить модули так, чтобы объединить логически связанные абстракции иминимизировать взаимные связи между модулями.
Исходя из этого, приведем определениемодульности:Модульность — это свойство системы, которая была разложена на внутренне связные,но слабо связанные между собой модули.Таким образом, принципы абстрагирования, инкапсуляции и модульности являютсявзаимодополняющими. Объект логически определяет границы определенной абстракции, аинкапсуляция и модульность делают их физически незыблемыми.В процессе разделения системы на модули могут быть полезными два правила. Во-первых,поскольку модули служат в качестве элементарных и неделимых блоков программы, которыемогут использоваться в системе повторно, распределение классов и объектов по модулям должноучитывать это. Во-вторых, многие компиляторы создают отдельный сегмент кода для каждогомодуля.
Поэтому могут появиться ограничения на размер модуля. Динамика вызовов подпрограмми расположение описаний внутри модулей может сильно повлиять на локальность ссылок и науправление страницами виртуальной памяти. При плохом разбиении процедур по модулямучащаются взаимные вызовы между сегментами, что приводит к потере эффективности кэшпамяти и частой смене страниц.На выбор разбиения на модули могут влиять и некоторые внешние обстоятельства. Приколлективной разработке программ распределение работы осуществляется, как правило, помодульному принципу и правильное разделение проекта минимизирует связи между участниками.При этом более опытные программисты обычно отвечают за интерфейс модулей, а менее опытные— за реализацию.
На более крупном уровне такие же соотношения справедливы для отношениймежду субподрядчиками. Абстракции можно распределить так, чтобы быстро установитьинтерфейсы модулей по соглашению между компаниями, участвующими в работе. Изменения винтерфейсе вызывают много крика и зубовного скрежета, не говоря уже об огромном расходебумаги, — все эти факторы делают интерфейс крайне консервативным. Что касаетсядокументирования проекта, то оно строится, как правило, также по модульному принципу —модуль служит единицей описания и администрирования.
Десять модулей вместо одногопотребуют в десять раз больше описаний, и поэтому, к сожалению, иногда требования подокументированию влияют на декомпозицию проекта (в большинстве случаев негативно). Могутсказываться и требования секретности: часть кода может быть несекретной, а дру гая —секретной; последняя тогда выполняется в виде отдельного модуля (модулей).Свести воедино столь разноречивые требования довольно трудно, но главное уяснить:вычленение классов и объектов в проекте и организация модульной структуры — независимыедействия. Процесс вычленения классов и объектов составляет часть процесса логическогопроектирования системы, а деление на модули — этап физического проектирования. Разумеется,иногда невозможно завершить логическое проектирование системы, не завершив физическоепроектирование, и наоборот. Два этих процесса выполняются итеративно.Примеры модульности.
Посмотрим, как реализуется модульность в гидропоннойогородной системе. Допустим, вместо закупки специализированного аппаратного обеспечения,решено использовать стандартную рабочую станцию с графическим интерфейсом пользователяGUI (Graphical User Interface).
С помощью рабочей станции оператор может формировать новыепланы выращивания, модифицировать имеющиеся планы и наблюдать за их исполнением. Так какабстракция плана выращивания — одна из ключевых, создадим модуль, содержащий все,относящееся к плану выращивания. На C++ нам понадобится примерно такой файл-заголовок(пусть он называется gplan.h).// gplan.h#ifndef _GPLAN_H#define _GPLAN_H 1#include "gtypes.h"#include "except.h"#include "actions.h"class GrowingPlan ...class FruitGrowingPlan ...class GrainGrowingPlan ...#endifЗдесь мы импортируем в файл три других заголовочных файла с определениеминтерфейсов, на которые будем ссылаться: gtypes.h, except .h и act ions. h.
Собственно код классовмы поместим в модуль реализации, в файл с именем gplan.cpp.Мы могли бы также собрать в один модуль все программы, относящиеся к окнам диалога,специфичным для данного приложения. Этот модуль наверняка будет зависеть от классов,объявленных в gplan.h, и от других файлов-заголовков с описанием классов GUI.Вероятно, будет много других модулей, импортирующих интерфейсы более низкогоуровня.
Наконец мы доберемся до главной функции — точки запуска нашей программыоперационной системой. При объектно-ориентированном проектировании это скорее всего будетсамая малозначительная и неинтересная часть системы, в то время, как в традиционномструктурном подходе головная функция — это краеугольный камень, который держит всесооружение. Мы полагаем, что объектно-ориентированный подход более естественен, поскольку,как замечает Мейер, «на практике программные системы предлагают некоторый набор услуг. Сводить их к одной функции можно, но противоестественно...
Настоящие системы не имеют верхнегоуровня» [63].ИерархияЧто такое иерархия? Абстракция — вещь полезная, но всегда, кроме самых простыхситуаций, число абстракций в системе намного превышает наши умственные возможности.Инкапсуляция позволяет в какой-то степени устранить это препятствие, убрав из поля зрениявнутреннее содержание абстракций.
Модульность также упрощает задачу, объединяя логическисвязанные абстракции в группы. Но этого оказывается недостаточно.Значительное упрощение в понимании сложных задач достигается за счет образования изабстракций иерархической структуры. Определим иерархию следующим образом:Иерархия — это упорядочение абстракций, расположение их по уровням.Основными видами иерархических структур применительно к сложным системамявляются структура классов (иерархия «is-a») и структура объектов (иерархия «part of»).Примеры иерархии: одиночное наследование. Важным элементом объектно-ориентированных систем и основным видом иерархии «is-a» является упоминавшаяся вышеконцепция наследования.
Наследование означает такое отношение между классами (отношениеродитель/потомок), когда один класс заимствует структурную или функциональную часть одногоили нескольких других классов (соответственно, одиночное и множественное наследование).Иными словами, наследование создает такую иерархию абстракций, в которой подклассынаследуют строение от одного или нескольких суперклассов. Часто подкласс достраивает илипереписывает компоненты вышестоящего класса.Семантически, наследование описывает отношение типа «is-a». Например, медведь естьмлекопитающее, дом есть недвижимость и «быстрая сортировка» есть сортирующий алгоритм.Таким образом, наследование порождает иерархию «обобщение-специализация», в которойподкласс представляет собой специализированный частный случай своего суперкласса.«Лакмусовая бумажка» наследования — обратная проверка; так, если в не есть А, то в не стоитпроизводить от А.Рассмотрим теперь различные виды растений, выращиваемых в нашей огородной системе.Мы уже ввели обобщенное представление абстрактного плана выращивания растений.
Однакоразные культуры требуют разных планов. При этом планы для фруктов похожи друг на друга, ноотличаются от планов для овощей или цветов. Имеет смысл ввести на новом уровне абстракцииобобщенный «фруктовый» план, включающий указания по опылению и сборке урожая. Вот какбудет выглядеть на C++ определение плана для фруктов, как наследника общего планавыращивания.// Тип Урожайtypedef unsigned int Yield;class FruitGrowingPlan : public GrowingPlan {public:FruitGrowingPlan(char* name);virtual ~FruitGrowingPlan();virtual void establish(Day, Hour, Condition&);void scheduleHarvest(Day, Hour);Boolean isHarvested() const;unsigned daysUntilHarvest() const;Yield estimatedYield() const;protected:Boolean repHarvested;Yield repYield;};Абстракцииобразуют иерархиюЭто означает, что план выращивания фруктов FruitGrowingPlan являетсяразновидностью плана выращивания Growingplan.
В него добавлены параметры repHarvestedи repYield, определены четыре новые функции и переопределена функция establish. Теперь мымогли бы продолжить специализацию — например, определить на базе «фруктового» плана«яблочный» класс AppleGrowingPlan.В наследственной иерархии общая часть структуры и поведения сосредоточена в наиболееобщем суперклассе.
По этой причине говорят о наследовании, как об иерархии обобщениеспециализация. Суперклассы при этом отражают наиболее общие, а подклассы — болееспециализированные абстракции, в которых члены суперкласса могут быть дополнены,модифицированы и даже скрыты. Принцип наследования позволяет упростить выражениеабстракций, делает проект менее громоздким и более выразительным. Кокс пишет: «В отсутствиенаследования каждый класс становится самостоятельным блоком и должен разрабатываться "снуля". Классы лишаются общности, поскольку каждый программист реализует их по-своему.Стройность системы достигается тогда только за счет дисциплинированности программистов.Наследование позволяет вводить в обращение новые программы, как мы обучаем новичков новымпонятиям — сравнивая новое с чем-то уже известным» [64].Принципы абстрагирования, инкапсуляции и иерархии находятся между собой в некоемздоровом конфликте.