ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 06.11.2023
Просмотров: 896
Скачиваний: 6
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
65
Все перечисленные структуры предполагают различные представле- ния и подходы к проектированию программной системы. Элементы од- ной структуры связаны с элементами прочих, и на эти отношения сле- дует обратить внимание. В частности, модуль в структуре декомпози- ции может декларироваться как отдельный компонент, как часть от- дельного компонента или несколько компонентов в рамках одной из структур “компонент и соединитель”, отражая, таким образом, своего представителя периода прогона.
В тоже время каждая рассмотренная структура снабжает архитекто- ра оригинальным представлением системы и дополнительной базовой точкой проектирования. Заметим, что современные CASE-средства про- ектирования архитектуры программных систем, например, Rational
Software Architect реализуют именно подобный подход при разработке программных систем, позволяя представлять архитектуру системы множеством взаимосвязанных моделей [4].
Иногда в рамках отдельных проектов одна структура считается ос- новной, а остальные структуры, если это возможно и нужно, определя- ются в ее категориях. Часто, хотя и не всегда, в качестве доминантной структуры выступает декомпозиция модулей. Объясняется это вполне разумно – декомпозиция модулей порождает структуру проекта.
Структуры – это основные базовые точки конструирования архитек- туры. Отдельные структуры отвечают за те или иные атрибуты качест- ва. Они выражают принцип разделения задач при создании архитекту- ры, а также при ее последующем анализе и изложении для заинтересо- ванных лиц. Например, если разработчик программного обеспечения желает внести в клиент-серверную структуру системы какие-либо изме- нения, он должен учитывать представления процессов и размещения.
Дело в том, что клиент-серверные механизмы, как правило, задействуют процессы и потоки, а физическое распределение реализует различные механизмы управления, которые оказываются необходимыми в случае локализации процессов на одной машине. При необходимости измене- ния механизмов управления оценить степень их корректировки помо- гают представление декомпозиции модулей и многоуровневое пред- ставление.
2.8. Варианты архитектур программных систем
Далее рассматриваем доминантные архитектуры программных сис- тем в смысле, определенном в предыдущее разделе. Архитектуры про- граммных систем менялись по мере развития информационных техно- логий. В 60-е годы ХХ века значительный процент систем составляли традиционные пакетные системы, которые представляли собой ряд ав- тономных последовательных программ, общающихся через файлы во вторичной памяти. Выделялись лишь два похода к построению систем: метод уровней абстракции и метод портов [17]. Позже получил развитие модульно-интерфейсный подход – один из методов структурного проек-
66 тирования, затем подходы, основанные на потоках данных, независи- мых компонентах, объектно-ориентированном проектировании и др.
Цель данного раздела – рассмотрение некоторых типичных вариан- тов архитектур программных системна основе классификации, приве- денной в [9, 17] , и материалах других публикаций [23 – 26].
2.8.1. Архитектура, основанная на уровнях абстракций
Ввиду важности концепции абстракций и широкого использования этой концепции в разработке архитектур различных сложных систем остановимся на этой концепции достаточно подробно. Наиболее мощ- ный инструмент, дающий разработчику возможность справиться со сложностью системы – это понятие абстракции. Абстракция представ- ляет собой описание системы или ее части, в котором не указываются абсолютно все детали. Она обеспечивает разработчику общий “макро- скопический” обзор системы, в силу чего дает представление о глобаль- ных связях и свойствах основных элементов системы, которое трудно достичь, когда учитываются все подробности.
Не существует такого понятия, как вполне определенная, единст- венная абстракция конкретной системы. Для каждой системы имеется множество возможных абстракций. Каждая абстракция дает разработ- чику различную точку зрения на то, как выглядит система и что она де- лает. Абстракции системы могут быть тесно связаны. Так, например, одна абстракция а(2) может быть уточнением абстракции а(1). Если аб- стракция а(2) уточняет абстракцию а(1), то абстракция а(2) описывает все, что описывает абстракция а(1), но уровень детализации в абстрак- ции а(2) всегда не меньше, чем в абстракции а(1). Другими словами аб- стракция а(2) является равномерно более детализированным описанием, чем а(1).
Пусть а(1), а(2),…, а(n) – такой ряд абстракций, что для каждого i аб- стракция а(i + 1) – уточнение предыдущей абстракции а(i). Каждая абстракция а(i) представляет собой полное, хотя и не обязательно под- робное описание всей системы. Когда абстракции упорядочены таким образом, имеет смысл говорить об уровне абстракции, т.е. о степени детализации описания.
Концепция уровней абстракции была предложена Дейкстрой в
1968году [17]. Программа разбивается на различные иерархически упо- рядоченные части L(1), L(2),…,L(n), называемые слоями (уровнями), удовлетворяющие определенным проектировочным критериям. Каждый уровень является группой тесно связанных модулей. Идея уровней при- звана минимизировать сложность системы за счет такого их определе- ния, которое обеспечивает высокую степень независимости уровней друг от друга. Это достигается благодаря тому, что свойства определен- ных объектов такой системы (ресурсы, представления данных и т. п.) упрятываются внутрь каждого уровня, что позволяет рассматривать ка- ждый уровень как абстракцию этих объектов.
67
На рис. 2.6 и 2.7 показаны возможные две общие структуры таких уровней.
Рис. 2.6. Вариант классической Рис. 2.7. Вариант произвольной структуры структуры
На рис. 2.6 показан такой подход, когда задача рассматривается как создание “машины пользователя”, начиная с самого низшего уровня аппаратуры (или возможно операционной системы). Последователь- ность уровней, называемых абстрактными машинами, определяется так, что каждая следующая машина строится на предыдущих, расширяя их возможности. Каждый уровень может ссылаться только на один, отлич- ный от него самого уровень (вызвать его), а именно тот, который непо- средственно ему предшествует.
В структуре, изображенной на рис. 2.7, уровни не являются полными абстракциями более низких уровней, каждый из них может ссылаться на любой предшествующий уровень.
Перечислим свойства уровней абстракции [17, 24]:
1. На каждом уровне абсолютно ничего не известно о свойствах ( и даже существовании) более высоких уровней. Это фундаментальное свойство уровней абстракции, существенно сокращающее число связей между частями программной системы и их предположений относитель- но свойств друг друга, благодаря чему уменьшается сложность системы.
2. На каждом уровне ничего не известно о внутреннем строении дру- гих уровней. Связь между уровнями осуществляется только через жест- кие, заранее определенные сопряжения.
3. Каждый уровень представляет собой группу модулей (раздельно компилируемых подпрограмм). Некоторые из этих модулей являются внутренними для уровня, т.е. недоступны для других уровней. Имена остальных модулей известны на следующем более высоком уровне. Эти имена представляют собой сопряжение с этим уровнем.
4. Каждый уровень располагает определенными ресурсами и либо скрывает их от других уровней (от более низких), либо предоставляет другим (более высоким) некоторые их абстракции. Например, в системе управления файлами один из уровней может содержать физические
68 файлы, скрывая их организацию от остальных частей системы. Другие уровни могут владеть такими ресурсами, как каталоги, словари данных, механизмы защиты.
5. Каждый уровень может обеспечивать некоторую абстракцию дан- ных в системе. Например, запись в базе данных – это абстракция таб- лицы данных, хранящееся в некотором файле.
6. Предположения, которые делаются на каждом уровне относитель- но других уровней, должны быть минимальны. Эти предположения мо- гут принимать вид соотношений, которые должны соблюдаться перед выполнением функции, либо относиться к представлению данных или факторов внешней среды.
7. Связи между уровнями ограничены явными аргументами, переда- ваемыми с одного уровня на другой. Недопустимо использование гло- бальных данных несколькими уровнями. Более того, желательно полно- стью исключить использование глобальных данных (даже внутри уров- ня) в системе.
8. Каждый уровень должен иметь высокую прочность и слабое сцеп- ление (дальше остановимся на этом более подробно). Это значит, что всякая функция, выполняемая уровнем абстракции, должна быть пред- ставлена единственным входом. Аргументы, пересылаемые между уровнями, должны быть отдельными элементами данных, анне слож- ными структурами.
Одной из первых программных систем, основанных на уровнях аб- стракции, была операционная система THE [17, 24]. Она является па- кетной системой с мультипрограммированием и виртуальной памятью.
Система включает пять уровней абстракции, структура которых близка к изображенной на рис. 2.7. Почему выбрана эта схема, а не схема по рис. 2.6?
На рис. 2.6 и 2.7 изображена последовательность слоев L(0), L(1),…,
L(n), причем L(0) – аппаратура, а L(1) – первый слой программ. Рас- смотрим вариант, когда слой L(i) может иметь доступ только к средст- вам виртуальной машины, определяемой слоем L(i -1). Если слою
L(i) потребуется какое-либо средство слоя L(i-2), то слой L(i -1) должен также предоставить это средство.
Рассмотрим теперь другой вариант, когда слой L(i) может использо- вать все средства, предоставляемые слоями L(1), L(2),…, L(i-1). Таким образом, виртуальная машина, определяемая слоем L(i) включает все команды до слоя L(i) и команды, реализуемые слоем L(i).
Третий вариант является промежуточным между двумя первыми. В этом случае слою L(i) разрешается использовать только некоторые из команд, обеспечиваемых слоями L(1), L(2),…, L(i-1).
В некоторых системах (например, в операционных системах) первый слой является единственным слоем, который может выдавать привиле- гированные команды аппаратному оборудованию. На рис. 2.8 представ- лена возможная многоуровневая иерархическая структура операцион- ной системы, в которой машинно-зависимые модули ядра (уровень L(1)) и базовые механизмы ядра (уровень L(2)) используют привилегирован-
69 ные команды процессора. Другие слои могут выполнять непривилеги- рованные команды плюс команды нижележащих слоев в соответствии с одним из трех рассмотренных выше вариантов.
Каждый вариант имеет свои достоинства и недостатки. Для их рас- смотрения обратимся к рис. 2.9. Здесь показано два варианта возможной структуры операционной системы: слева (рис. 2.9-а) вариант структуры с многоуровневым модульным ядром и справа (рис. 2.9-б) – вариант структуры с компактным микроядром [19]. Если в варианте 2.9-а каж- дый слой имеет доступ к командам только одного слоя, разработчик должен иметь в виду только предыдущий слой. Хотя с точки зрения проектирования этот вариант кажется привлекательным, он может ока- заться очень неэффективным.
Рис. 2.8. Многоуровневая иерархическая структура операционной системы
Например, если некоторое средство, предоставляемое слоем L(2) – базовые механизмы ядра – потребуется в слое L(i), то каждый из слоев
L(3), L(4),..., L(i-1) должен обеспечить это средство. Это значит, что запрос данного средства слоем L(i) должен “просачиваться” вниз через слой L(i-1), пока не достигнет слоя L(2), который способен выполнить запрос. Эти трудности, связанные с проблемой эффективности, могут склонить к принятию структуры, в которой каждый слой L(i), где 2< I < n, может непосредственно обращаться к слою L(2), реализующему ба- зовые механизмы ядра. Так, например, организована операционная сис- тема Windows 2000/2003/XP (рис. 2.10).
70
Рассмотрим теперь вариант по рис. 2.9 б). В данном случае выделено три слоя (два в микроядре) и третий – остальные модули системы. При этом, если какой либо компонент (модуль) третьего слоя потребует функцию другого компонента этого же слоя, то такая услуга может быть получена только через микроядро. В данном случае взаимодейст- вие модулей слоев организовано по принципу клиент-серверной архи- тектуры (рис. 2.11), эффективность которого может быть выше по срав- нению с вариантом по рис. 2.9а) при условии доступа модулей слоя L(i) только к слою L(i-1). а) многоуровневое ядро б) микроядерное ядро
Рис. 2.9. Варианты структур операционных систем
Рис. 2.10. Архитектура ОС Windows 2000/2003/XP
71
Рис. 2.11. Клиент-серверная архитектура ОС
Однако производительность микроядерной ОС в целом ниже произ- водительности архитектуры, приятой в упомянутых системах Windows
2000/2003/XP по причине возможного многократного переключения работы компьютера из пользовательского режима в режим ядра при вы- полнении системных вызовов (рис. 2.12).
Рис. 2.12. Переключение режимов работы в макроядерных и микроядерных ОС
В заключение данного раздела отметим, что можно построить дре- вовидную структуру слоев системы (рис. 2.13), в которой каждый слой может иметь доступ только к тем слоям, которые соответствуют его предшественникам по дереву. Дерево частей такой программы пред- ставляет на самом деле дерево виртуальных машин. Такая организация
72 была впервые использована при создании ядра операционной системы
SUE, разработанной в университете Торонто в 1972 году для семейства машин IBM/360 [24].
Рис. 2.13. Организация ядра операционной системы SUE
2.8.2. Архитектуры, основанные на портах
В отличие от метода уровней абстракции, где внимание в первую очередь уделяется правильному распределению функций между уров- нями иерархии в системе, здесь основное внимание обращено на мето- ды связи между подсистемами. Механизмы, обеспечивающие взаимо- действие между частями системы, можно разбить на три группы. Меха- низмы первой группы, такие как предложение GOTO, прерывание, сис- темный вызов, передают управление от одной части программы другой, не передавая явно никаких данных.
Механизмы типа вызова процедуры или подпрограммы относятся ко второй группе; они передают от одной части системы к другой и управ- ление и данные. К третьей группе относятся механизмы портов – это методы передачи данных без передачи управления [17].
При использовании механизма портов программная система делится на несколько подсистем, каждая из которых может иметь один или не- сколько входных портов (одну или несколько входных очередей). Порт
– это просто текущий список входных сообщений (список параметров) для подсистемы. Каждая подсистема рассматривается как асинхронный процесс, т.е. все подсистемы работают параллельно. Если одна из них хочет передать некоторые данные другой, она посылает их во входной порт этой другой подсистемы. Если подсистема готова обрабатывать какие-то данные, она читает их из одного из своих входных портов. Для организации такой связи используются операции ПОСЛАТЬ и ПОЛУ-
ЧИТЬ.
Механизм портов увеличивает независимость подсистем, освобож- дая их от временной зависимости, друг от друга. Более того, подсисте- мы не должны даже знать о взаимном расположении. Только механизм посылки-получения (почта) должен знать расположение каждой подсис-
73 темы (например, в той же виртуальной памяти, в другой виртуальной памяти, в другом компьютере и т. д.). На рис. 2.14 изображена подсис- тема программной системы (процесс), имеющий несколько первичных входных портов, по одному для каждой функции процесса. Процесс может выполнять команды типа ПОЛУЧИТЬ_ПОРТi (A,B,C), по кото- рой из входного порта ПОРТi выбирается очередное сообщение и выде- ленные из него аргументы присваиваются параметрам A,B,C.
Рис. 2.14. Архитектура системы на основе портов прямой конфигурации
Процесс может послать данные другим процессам в результате вы- полнения команд ПОСЛАТЬ_УПРДАННЫМИ (Х, У), по которой из аргументов Х, У формируется сообщение, пересылаемое в порт по име- ни УПРДАННЫМИ. У процесса может быть и другой набор портов – вторичные порты. Они используются для связи с подчиненными про- цессами. Например, подчиненный процесс может поставлять данные из базы данных.
Процесс, показанный на рис. 2.14, – часть прямой конфигурации.
Каждый такой процесс осуществляет связь посылкой сообщения прямо во входной порт другого процесса. На рис. 2.15 изображен процесс, яв- ляющийся частью непрямой конфигурации. Процессы этого типа имеют выходные порты. Вместо того чтобы посылать сообщения во входные порты других процессов, они посылают сообщения в свои выходные порты. Выходной порт связывается с входными портами других процес- сов посредством специальных указаний, например в компьютерах третьего поколения, на языке управления заданиями. Физически выход- ные порты не существуют, это абстрактные наименования для входных портов других процессов.
На рис. 2.16 приведена схема информационно-поисковой системы, использующей прямую конфигурацию [17]. Управление терминалами – это непрерывно выполняемый процесс, который опрашивает терминалы пользователей и, получив команду с терминала, посылает сообщение подсистеме интерпретации команд. Сообщение состоит из двух аргу- ментов: идентификатора терминала и команды. Управление терминалом выполняет также функцию выдачи на терминал выходных строк. Полу- чив команду с терминала подсистема интерпретации команд, использу- ет две подчиненные системы, чтобы подготовить ключ для поиска и