ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.11.2023
Просмотров: 928
Скачиваний: 6
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
257
Отметим, что типы связности 1,2,3 – результат неправильного пла- нирования архитектуры, а тип связности 4 – результат небрежного пла- нирования архитектуры приложения. Общая характеристика типов связности представлена в табл. 6.1.
Табл. 6.1.
Характеристика типов связности
Тип связности
Сопровождаемость
Роль модуля
Функциональная
«Черный ящик»
Информационная
( последовательная )
Лучшая сопровождаемость
Не совсем
«черный ящик»
Коммуникативная
«Серый ящик»
Процедурная
«Белый» или «просве- чивающий ящик»
Временная
Худшая сопровождаемость
Логическая
«Белый ящик»
По совпадению
Рассмотрим теперь каждый тип связности более подробно.
Функциональная связность. Функционально связный модуль содер- жит элементы, участвующие в выполнении одной и только одной про- блемной задачи. Примеры функционально связных модулей [30]:
Вычислять синус угла;
Проверять орфографию;
Читать запись файла;
Вычислять координаты цели.
Каждый из этих модулей имеет единичное назначение. Когда клиент вызывает модуль, выполняется только одна работа, без привлечения внешних обработчиков. Некоторые из функционально связных модулей очень просты (например, Вычислять синус угла или Читать запись фай- ла), другие сложны (например, Вычислять координаты цели). Модуль
Вычислять синус угла, очевидно, реализует единичную функцию, но как может модуль Вычислять зарплату сотрудника выполнять только одно действие?
Известно, что в этом случае приходится определять начисленную сумму, вычеты по рассрочкам, подоходный налог, алименты и т. д. Де- ло в том, что, несмотря на сложность модуля и на то, что его обязан- ность исполняют несколько подфункций, если его действия можно представить как единую проблемную функцию (с точки зрения клиен- та), считают, что модуль функционально связен.
Приложения, построенные из функционально связных модулей, лег- че всего сопровождать. Соблазнительно думать, что любой модуль можно рассматривать как однофункциональный, но не надо заблуж- даться. Существует много разновидностей модулей, которые выполня- ют для клиентов перечень различных работ, и этот перечень нельзя рас-
258 сматривать как единую проблемную функцию. Критерий при определе- нии уровня связности этих нефункциональных модулей в установлении того, как связаны друг с другом различные действия, которые они ис- полняют.
Информационная связность. При информационной (последователь- ной) связности элементы-обработчики модуля образуют конвейер для обработки данных – результаты одного обработчика используются как исходные данные для следующего обработчика. Например, Модуль
Прием и проверка записи может содержать следующие элементы- обработчики: прочитать запись из файла, проверить контрольные данные в записи, удалить контрольные поля в записи, вернуть обработанную запись.
В этом модуле 4 элемента. Результаты первого элемента (прочитать запись из файла) используются как входные данные для второго эле- мента (проверить контрольные данные в записи) и т. д. Сопровождать модули с информационной связностью почти так же легко, как и функ- ционально связные модули. Правда, возможности повторного использо- вания здесь ниже, чем в случае функциональной связности. Причина – совместное применение действий модуля с информационной связно- стью полезно далеко не всегда.
Коммуникативная связность. При коммуникативной связности эле- менты-обработчики модуля используют одни и те же данные, например внешние данные. Пример коммуникативно связного модуля – Модуль
Отчет и средняя зарплата. В данном случае используется Таблица зар- платы служащих со следующими элементами-обработчиками: сгенерировать Отчет по зарплате; вычислить параметр Средняя зарплата; вернуть Отчет по зарплате. Средняя зарплата.
Здесь все элементы модуля работают со структурой Таблица зарпла- ты служащих.
С точки зрения клиента проблема применения коммуникативно связного модуля состоит в избыточности получаемых результатов. На- пример, клиенту требуется только отчет по зарплате, он не нуждается в значении средней зарплаты. Такой клиент будет вынужден выполнять избыточную работу – выделение в полученных данных материала отче- та. Почти всегда разбиение коммуникативно связного модуля на от- дельные функционально связные модули улучшает сопровождаемость системы.
Попытаемся провести аналогию между информационной и комму- никативной связностью. Модули с коммуникативной и информацион- ной связностью подобны в том, что содержат элементы, связанные по данным. Их удобно использовать, потому что лишь немногие элементы в этих модулях связаны с внешней средой. Главное различие между ни- ми – информационно связный модуль работает подобно сборочной ли- нии; его обработчики действуют в определенном порядке; в коммуника-
259 тивно связном модуле порядок выполнения действий безразличен. В нашем примере не имеет значения, когда генерируется отчет (до, после или одновременно с вычислением средней зарплаты).
Процедурная связность. При достижении процедурной связности мы попадаем в пограничную область между хорошей сопровождаемостью
(для модулей с более высокими уровнями связности) и плохой сопро- вождаемостью (для модулей с более низкими уровнями связности).
Процедурно связный модуль состоит из элементов, реализующих неза- висимые действия, для которых задан порядок работы, то есть порядок передачи управления. Зависимости по данным между элементами нет.
Например, Модуль Вычисление средних значений использует Таблица-
А и Таблица-В и содержит элементы (пример из [30]): вычислить среднее по Таблица-А; вычислить среднее по Таблица-В; вернуть среднееТабл-А. и среднееТабл-В.
Этот модуль вычисляет средние значения для двух полностью несвя- занных таблиц Таблица-А и Таблица-В, каждая из которых имеет по 300 элементов.
Теперь представим себе программиста, которому поручили реализо- вать данный модуль. Соблазнившись возможностью минимизации кода
(использовать один цикл в интересах двух обработчиков, ведь они на- ходятся внутри единого модуля!), программист пишет:
//Модуль Вычисление средних значений
//используется Таблица-А. Таблица-В
суммаТабл-А := 0
суммаТабл-В := 0
для i := 1 до 300
суммаТабл-А := суммаТабл-А + Таблица-А(i)
суммаТабл-В :- суммаТабл-В + Таблица-В(i)
конец для
среднееТабл-А := суммаТабл-А / 300
среднееТабл-В := суммаТабл-В / 300
вернуть среднееТабл-А, среднееТабл-В
//Конец модуля
Для процедурной связности этот случай типичен – независимый (на уровне проблемы) код стал зависимым (на уровне реализации). Прошли годы, продукт сдали заказчику. И вдруг возникла задача сопровождения
– модифицировать модуль под уменьшение размера таблицы В. Оцени- те, насколько удобно ее решать.
Временная связность. При связности по времени элементы- обработчики модуля привязаны к конкретному периоду времени (из жизни программной системы).
Классическим примером временной связности является модуль ини- циализации [30]:
260
//Модуль Инициализировать Систему
перемотать магнитную ленту 1
Счетчик магнитной ленты 1 := 0
перемотать магнитную ленту 2
Счетчик магнитной ленты 2 := 0
Таблица текущих записей : = пробел..пробел
Таблица количества записей := 0..0
Переключатель 1 : = выкл
Переключатель 2 := вкл
// Конец модуля
Элементы данного модуля почти не связаны друг с другом (за ис- ключением того, что должны выполняться в определенное время). Они все – часть программы запуска системы. Зато элементы более тесно взаимодействуют с другими модулями, что приводит к сложным внеш- ним связям.
Модуль со связностью по времени приводит к тем же трудностям, что и процедурно связный модуль. Программист соблазняется возмож- ностью совместного использования кода (действиями, которые связаны только по времени), модуль становится трудно использовать повторно.
Так, при желании инициализировать магнитную ленту 2 в другое время можно столкнуться с неудобствами. Чтобы не сбрасывать всю систему, придется или ввести флажки, указывающие инициализируемую часть, или написать другой код для работы с лентой 2. Оба решения ухудшают сопровождаемость.
Процедурно связные модули и модули с временной связностью очень похожи. Степень их непрозрачности изменяется от темного серо- го до светло-серого цвета, так как трудно объявить функцию такого мо- дуля без перечисления ее внутренних деталей. Различие между ними подобно различию между информационной и коммуникативной связно- стью. Порядок выполнения действий более важен в процедурно связных модулях. Кроме того, процедурные модули имеют тенденцию к совме- стному использованию циклов и ветвлений, а модули с временной связ- ностью чаще содержат более линейный код.
Логическая связность. Элементы логически связного модуля при- надлежат к действиям одной категории, и из этой категории клиент вы- бирает выполняемое действие. Рассмотрим следующий пример [30]:
// Модуль Пересылка сообщения
переслать по электронной почте
переслать по факсу
послать в телеконференцию
переслать по ftp-протоколу
// Конец модуля
Как видно, логически связный модуль – “мешок” доступных дейст- вий. Действия вынуждены совместно использовать один и тот же ин-
261 терфейс модуля. В строке вызова модуля значение каждого параметра зависит от используемого действия. При вызове отдельных действий некоторые параметры должны иметь значение пробела, нулевые значе- ния и т. д. (хотя клиент все же должен использовать их и знать их типы).
Действия в логически связном модуле попадают в одну категорию, хотя имеют не только сходства, но и различия. К сожалению, это за- ставляет программиста «завязывать код действий в узел», ориентируясь на то, что действия совместно используют общие строки кода. Поэтому логически связный модуль имеет: уродливый внешний вид с различными параметрами, обеспечиваю- щими, например, четыре вида доступа; запутанную внутреннюю структуру со множеством переходов, по- хожую на волшебный лабиринт.
В итоге модуль становится сложным как для понимания, так и для сопровождения.
Связность по совпадению. Элементы связного по совпадению моду- ля вообще не имеют никаких отношений друг с другом:
// Модуль Разные функции (какие-то параметры)
поздравить с Новым годом (...)
проверить исправность аппаратуры (...)
заполнить анкету героя (...)
измерить температуру (...)
вывести собаку на прогулку (...)
запастись продуктами (...)
приобрести «ягуар» (...)
// Конец модуля
Связный по совпадению модуль похож на логически связный мо- дуль. Его элементы-действия не связаны ни потоком данных, ни пото- ком управления. Но в логически связном модуле действия, по крайней мере, относятся к одной категории; в связном по совпадению модуле даже это не так. Словом, связные по совпадению модули имеют все не- достатки логически связных модулей и даже усиливают их. Применение таких модулей вселяет ужас, поскольку один параметр используется для разных целей.
Чтобы клиент мог воспользоваться модулем Разные функции, этот модуль (подобно всем связным по совпадению модулям) должен быть
«белым ящиком», чья реализация полностью видима. Такие модули де- лают системы менее понятными и труднее сопровождаемыми, чем сис- темы без модульности вообще!
Обычно связность по совпадению встречается редко. Среди ее при- чин можно назвать: бездумный перевод существующего монолитного кода в модули; необоснованные изменения модулей с плохой (обычно временной) связностью, приводящие к добавлению флажков.
262
Для определения связности модуля можно использовать следующий алгоритм:
1. Если модуль – единичная проблемно-ориентированная функция, то уровень связности – функциональный; конец алгоритма. В против- ном случае перейти к пункту 2.
2. Если действия внутри модуля связаны, то перейти к пункту 3. Ес- ли действия внутри модуля никак не связаны, то перейти к пункту 6.
3. Если действия внутри модуля связаны данными, то перейти к пункту 4. Если действия внутри модуля связаны потоком управления, перейти к пункту 5.
4. Если порядок действий внутри модуля важен, то уровень связно- сти – информационный. В противном случае уровень связности – ком- муникативный. Конец алгоритма.
5. Если порядок действий внутри модуля важен, то уровень связно- сти – процедурный. В противном случае уровень связности – времен- ной. Конец алгоритма.
6. Если действия внутри модуля принадлежат к одной категории, то уровень связности – логический. Если действия внутри модуля не при- надлежат к одной категории, то уровень связности – по совпадению.
Конец алгоритма.
Возможны более сложные случаи, когда с модулем ассоциируются несколько уровней связности. В этих случаях следует применять одно из двух правил: правило параллельной цепи. Если все действия модуля имеют не- сколько уровней связности, то модулю присваивают самый сильный уровень связности; правило последовательной цепи. Если действия в модуле имеют раз- ные уровни связности, то модулю присваивают самый слабый уро- вень связности.
Например, модуль может содержать некоторые действия, которые связаны процедурно, а также другие действия, связные по совпадению.
В этом случае применяют правило последовательной цепи и в целом модуль считают связным по совпадению.
6.2.4. Сцепление модулей – внешняя характеристика модуля
Сцепление (Coupling) – мера взаимозависимости модулей по дан- ным [3]. Сцепление – внешняя характеристика модуля, которую жела- тельно уменьшать. Независимые модули могут быть модифицированы без переделки каких-либо других модулей. Количественно сцепление измеряется степенью сцепления (СЦ). Выделяют 7 типов сцепления.
Следует заметить, что у различных авторов [14, 20, 30] могут быть не- которые различия в оценке сцепления.
1. Полностью независимые модули (СЦ=0). Модули, не вызывающие друг друга и не использующие общих данных, не сцеплены и являются
263 полностью независимыми. Чем больше информации о других модулях используется в них, тем менее они независимы и тем сильнее сцеплены.
2. Сцепление по данным (СЦ=1). Модуль А вызывает модуль В. Все входные и выходные параметры вызываемого модуля – простые эле- менты данных.
3. Сцепление по образцу (СЦ=3). В этом случае модули ссылаются на одну и ту же глобальную структуру данных. Недостатком такого сцеп- ления является то. Что оба модуля должны знать о внутренней структу- ре данных. Если программист, сопровождающий программу, модифи- цирует структуру данных в одном из модулей, он вынужден изменить структуру данных также и в другом.
4. Сцепление по общей области (СЦ=5). Модули разделяют одну и ту же глобальную структуру данных. В этом случае возможностей для появления ошибок при модификации структуры данных в одном модуле много больше. По изменениям, производимых в объявленных парамет- рах, сразу можно определить модули, на которые эти изменения по- влияют. Если модифицируются неявно заданные параметры, определить модули, нуждающиеся в корректировке, труднее, если только не суще- ствует документации, отражающей использование модулями общих областей.
5. Сцепление по управлению (СЦ=7). Модуль А явно управляет функционированием модуля В с помощью передачи флагов, переключа- телей или кодов, посылая ему управляющие данные. Возвращение фла- га состояния как неявной переменной не означает сцепление по управ- лению. Если модуль передает информацию о самом себе или об обрабо- танных данных, то это не всегда служит проявлением сцепления по управлению. Передача флага конца файла позволяет решить вопрос о возможности обработки этого файла.
Установка флага, указывающего, какой именно способ доступа ис- пользуется в операции обмена (последовательный или прямой), означа- ет, что осуществляется сцепление по управлению, когда это влияет на модуль обмена. Если модуль имеет логическую связность и при его вы- зове используется переключатель, указывающий на требуемую функ- цию, вызываемый и вызывающий модули сцеплены по управлению.
6. Сцепление по внешним ссылкам (СЦ=9). Модуль имеет сцепление по внешним ссылкам, если у него есть доступ к данным в другом моду- ле через внешнюю точку входа. Таким путем осуществляется неявное управление функционированием другого модуля. Сцепление такого ти- па возникает, например, при использовании некоторых языков про- граммирования (Паскаль), когда внутренние процедуры оперируют с глобальными переменными.
7. Сцепление по кодам (содержанию) (СЦ=10). Один модуль прямо ссылается на содержание другого модуля (не через его точку входа).
Например, коды их команд перемежаются друг с другом.
264
1 ... 19 20 21 22 23 24 25 26 ... 37