МОДУЛЬНОСТЬ.docx

  • docx
  • 29.04.2020
Публикация на сайте для учителей

Публикация педагогических разработок

Бесплатное участие. Свидетельство автора сразу.
Мгновенные 10 документов в портфолио.

Иконка файла материала МОДУЛЬНОСТЬ.docx

МОДУЛЬНОСТЬ

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

Реализация модулей. Модульности можно достичь многими способами. В главах 4 и 5 было показано, как можно реа- лизовать модули в виде отдельных процедур, которые впоследствии используются в качестве конструкционных элементов для построения систем большего размера. В главе 5 модульность также обсуждалась в контексте объектно- ориентированного подхода. В этом случае модули принимали форму объектов, каждый из которых имел собственную внут- реннюю организацию, не зависящую от содержимого других объектов. Фактически рост популярности объектно- ориентированного подхода к разработке программного обеспечения в значительной степени можно объяснить именно мо- дульной структурой, изначально присущей этому методу.


Структурная схема – это традиционное средство представления модульной структуры, достигаемой за счет создания процедур. На этой схеме каждый модуль (процедура) представляется прямоугольником, а связи между ними – стрелками, соединяющими эти прямоугольники. Структурная схема, представленная на рис. 6.3, отображает модульную структуру про- стой ролевой игры в жанре фантази, в которой игрок должен передвигаться по комнатам средневекового замка, решая в каж- дой некоторую задачу, прежде чем ему будет позволено перейти в следующее помещение. На схеме показано, что модуль с именем CoordinateGame (Координировать игру) использует модули InitializeGame (Инициализировать игру), SimulateGreatHall (Имитация большого зала), SimulateDungeon (Имитация темницы) и SimulateTurret (Имитация

Рис. 6.3. Структурная схема простой ролевой игры

 

башни) в качестве абстрактных средств решения задачи. Точнее говоря, процедура CoordinateGame вызывает процедуру InitializeGame для организации начала игры (узнать имя игрока, установить уровень сложности игры – начинающий, средний или сложный – и т.д.). После каждого перехода игрока на новый уровень (т.е. перехода в следующую комнату) процедура CoordinateGame вызывает другую процедуру, выполняющую имитацию требуемой комнаты, чтобы организовать выполне- ние происходящих в этой комнате событий. Кроме того, на схеме показано, что каждый из модулей имитации комнаты об- ращается к процедуре UpdateScore (Обновление счета), чтобы записать результаты, достигнутые игроком в данной комнате.

В то время как структурные схемы используются для представления внутренней структуры программного обеспечения с процедурной организацией, диаграммы классов применяются для представления структуры систем с объектно- ориентированной организацией. Диаграмма классов определяет набор существующих в системе классов объектов и описы- вает взаимоотношения этих классов. На рис. 6.4 представлена простая диаграмма классов для упомянутой выше ролевой игры. На этой диаграмме показано, что система состоит из объектов двух типов, PlayRecord (Запись игрока) и Room (Комна- та), связанных отношением IsCurrentlyln (В данный момент внутри). Здесь объект типа PlayRecord содержит данные и процеду- ры, относящиеся к конкретному игроку (имя, уровень, результат), а объект типа Room данные и процедуры, относящиеся к опре- деленной комнате (образ комнаты, возникающий на экране, и связанные с этой комнатой задачи).


Рис. 6.4. Диаграмма классов для простой ролевой игры

 

Отношение IsCurrentlyln представляет связи, существующие между комнатами и игроками, т.е. запись игрока связывается с комнатой, в которой он в данный момент находится. Числа, указанные на концах линий, представляющих данное отноше- ние, показывают, что один игрок в конкретный момент времени может быть связан только с одной комнатой. Такая связь типа "один к одному" отличается от связи "один ко многим", примером которой может служить связь "обучать", когда один преподаватель ведет на протяжении семестра сразу несколько курсов.

В последние годы был достигнут значительный прогресс в разработке стандартной системы обозначений для представ- ления элементов в процессе объектно-ориентированного проектирования. Наиболее ярким примером является язык UML (Unified Modeling Language – унифицированный язык моделирования), представляющий собой унифицированную систему для представления множества объектно-ориентированных понятий. Обозначения, используемые на рис. 6.4, основаны на стандартах языка UML.

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

Связанность модулей системы может существовать в нескольких различных формах. Одна из них – это связанность по управлению.

В этом случае один модуль передает управление другому так, как это происходит при возврате и передаче управления между отдельными процедурами в программе. Другая форма – это связанность по данным, т.е. совместное использование одних и тех же данных несколькими модулями.

Структурная схема, представленная на рис. 6.3, отражает связанность модулей по управлению при процедурном подхо- де к построению упоминаемой выше ролевой игры. На структурной схеме связанность по данным обычно представляется с помощью дополнительных стрелок (рис. 6.5). На этой схеме изображено, какие элементы данных передаются модулю при обращении к предоставляемым им сервисам и какие возвращаются вызывающему модулю при завершении выполнения за- прошенной функции. В частности, на данной схеме показано, что модуль CoordinateGame при обращении к процедуре SimulateGreatHall передает ей значение уровня игрока. Обратите внимание, что модуль CoordinateGame, в свою очередь, по- лучает значение уровня игрока от процедуры InitializeGame. Кроме того, на схеме показано, что когда любой из модулей имитации помещения обращается с запросом к процедуре UpdateScore, он передает ей данные о количестве очков, уже на- бранных игроком.

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

Рис. 6.5. Структурная схема, содержащая сведения

o связанности по данным


Рис. 6.6. Диаграмма взаимодействий для простой ролевой игры

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

Один из способов представления связей между объектами в объектно-ориентированном проектировании состоит во внесении информации в диаграмму классов в целях построения диаграммы взаимодействий, которая, по существу, является диаграммой классов, показывающей, как различные объекты системы взаимодействуют друг с другом. Простая диаграмма взаимодействий для нашей ролевой игры (с использованием обозначений языка UML) представлена на рис. 6.6. На ней пока- зано, что объект класса Room может послать сообщение объекту класса PlayerRecord, предлагая ему обновить значение сче- та, а объект класса PlayerRecord может послать сообщение объекту класса Room, запрашивая у него сведения об очередном помещении.

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

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

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

Более сильная форма связности – функциональная связность; она означает, что все части модуля собраны вместе для выполнения одних и тех же действий. Модуль SimulateGreatHall, показанный на рис. 6.3, нельзя считать функционально связным, если он содержит сведения, необходимые для создания изображения на экране большого зала замка, представления всех связанных с этим залом задач и обработки ответных действий игрока. Однако если эти детали локализованы в других модулях и используются модулем SimulateGreatHall в качестве абстрактных инструментов, то каждый этап работы этого мо- дуля можно рассматривать в общем контексте наблюдения за действиями игрока, связанными с большим залом замка. В этом случае модуль SimulateGreatHall выглядит более функционально связным.

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


Рис. 6.7. Логическая и функциональная связность внутри объекта, представляющего отдельную комнату в простой ролевой игре

 

Вопросы для самопроверки

1.   Чем роман отличается от энциклопедии в смысле степени связанности, существующей между его элементами, таки- ми, как главы, разделы или отдельные записи? Что можно сказать о связности этих элементов?

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

3.   Совместимы ли задачи максимизации связности и минимизации связанности? Другими словами, будет ли естествен- ным образом уменьшаться связь модулей системы при возрастании связности элементов модулей?

4.  Расширьте диаграмму взаимодействий, представленную на рис. 6.6, включив в нее другие сообщения, которые долж- ны передаваться между объектами классов Room и PlayerRecord.