АРХИТЕКТУРА ПРОГРАММНЫХ СИСТЕМ

Понятие архитектуры программной системы

Разработка архитектуры системы — это процесс разбиения большой системы на более мелкие части. Для обозначения этих частей придумано множество названий: программы, компоненты, подсистемы...

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

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

Примеры систем: ОС, СУБД, система продажи авиабилетов и др.

Примеры программ: редактор текстов, компилятор, программы посылки запросов от кассира и др.

Понятие архитектуры программной системы можно проиллюст­рировать на следующем примере. Пусть имеется на неком пред­приятии некая САПР. Допустим, что предприятие достаточно крупное, и САПР будет являться целым комплексом различных программных продуктов, причем зачастую различных производите­лей. Архитектурой этой системы будет являться описание связей этих программных средств в одно целое. Глазами программиста: САПР — комплекс комплексов программ.

Системы из отдельных программ

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

Близкий аналог этой системы — система, управляемая команд­ным файлом. Простейшая архитектура такой системы реализуется последовательным вызовом каждой из программ. Программы об­мениваются данными через файлы, записанные на диске, или че­рез элементы данных, которые находятся в оперативной памяти ЭВМ по известным абсолютным адресам.

Уже в конце 70-х годов этим способом можно было быстро реа­лизовать весьма удобный ввод данных в программу.

Вместо стандартного монитора командных файлов для вызова в произвольном порядке уже готовых программ можно написать программу своего монитора на основе подпрограммы вызова гото­вых программ.

Хотя проектирование систем из отдельных программ выполня­ется, по крайней мере, последние 30 лет, но не выработано ника­кой методики, кроме не особенно полезного совета: изобразите функциональную схему процесса, а затем разбейте процесс на про­граммы.

 

Системы из отдельных резидентных программ

Резидентная программа — программа, которая постоянно нахо­дится в оперативной памяти машины и не препятствует запуску новых программ. После запуска резидентная программа становится как бы частью операционной системы MS DOS путем изменения значения границы памяти операционной системы, далее она на­страивает какое-то прерывание на передачу управления в свою точ­ку входа, а затем завершает работу. Можно запустить еще несколь­ко резидентных программ и обычную программу. После выполне­ния заданных прерываний MS DOS запускаются соответствующие резидентные программы.

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

Системы из программ, обменивающихся данными через порты

 

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

Подход к проектированию архитектуры системы на основе

абстрактных машин Дейкстры

 

Самый нижний уровень абстракции — это уровень аппаратуры. Каждый уровень реализует абстрактную машину с все большими возможностями.

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

Принцип 2. На каждом уровне ничего не известно о внутреннем строении других уровней. Связь уровней осуществляется только че­рез определенные заранее сопряжения.

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

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

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

Принцип 6. Предположения, которые на каждом уровне делают­ся относительно других уровней, должны быть минимальными, эти предположения могут принимать вид соглашений, которые долж­ны соблюдаться перед выполнением функций, либо относиться к представлению данных или факторов внешней среды.

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

Принцип 8. Всякая функция, выполняемая уровнем абстракции, должна быть представима единственным входом. Аргументы, пере­сылаемые между уровнями, должны быть отдельными элементами данных, а не сложными структурами.

 

Подход к проектированию архитектуры системы на основе абст­рактных машин Дейкстры можно пояснить на следующем примере.

Процессор фирмы «Intel» может лишь выполнять операции арифметики и, осуществляя сравнения двух величин, может вы­полнять команды перехода на команды в заданных адресах памяти. Программировать такую ЭВМ можно в виде прямой записи двоич­ных команд.

ЭВМ IBM PC имеет специальное постоянное запоминающее устройство с программами BIOS. После установки BIOS получает­ся машина с дополнительными командами загрузки программы с дисков, чтения информации из любого сектора дисков, чтения символа с клавиатуры, вывода информации на экран и т. д. Благо­даря прерываниям BIOS, становится возможным использование арифметики с плавающей точкой как при наличии, так и отсутст­вии сопроцессора.

После установки операционной системы MS DOS на машину IBM PC получается машина с новой поддержкой данных в виде фай­лов и с новыми командами работы над файлами и директориями (копирования, удаления и т. д.). Новая машина может выполнять опера­ции над вещественными числами с плавающей точкой. Появляются команды запуска выполняемых файлов и другие новые команды.

После установки операционной системы MS Windows 3.1 (при установке операционной системы MS Windows 95 одновременно устанавливается и MS DOS) появляются новые команды управле­ния окнами для работы специалистов «со столами, заваленными бумагами». Появляется возможность одновременного запуска раз­ных программ в разных окнах с возможностью междуоконного об­мена информацией.

После установки программного комплекса Microsoft Office по­являются среды и команды работы над документами, расчетными таблицами и т. д.

 

Сом - технология разработки развивающихся и рассредоточенных

комплексов программ

СОМ — Component Object Model (модель компонентных объек­тов) — это спецификация метода создания компонент и построе­ния из них программ.

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

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

Компоненты СОМ представляют собой исполняемый код, обычно распространяемый в виде динамически компонуемых биб­лиотек (DLL). Компоненты СОМ подключаются друг к другу дина­мически.

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

СОМ — это инструмент разработки развивающихся и рассредо­точенных (многомашинных) комплексов программ, основанная на модели компонентных объектов.

Главное в СОМ — следование стандартным спецификациям интерфейса компонент. Однажды принятый стандарт специфика­ций интерфейса никогда не изменяется. Однако после разработки нового стандарта новые компоненты сами будут опознавать старый и новый стандарты. После замены некоторого числа компонент программа вдруг заработает по-новому.

По мере развития программы, компоненты, составляющие про­грамму, могут заменяться новыми. Программа более не является статичной, обреченной устареть еще до выхода в свет. Вместо этого она постепенно эволюционирует с заменой старых компонент но­выми. Из существующих компонент легко создать и абсолютно но­вые программы.

Пользователи часто хотят адаптировать программы к своим ну­ждам. Конечные пользователи предпочитают, чтобы программа ра­ботала так, как они привыкли. Программистам в крупных органи­зациях нужны адаптируемые приложения, чтобы создавать специа­лизированные решения на основе готовых продуктов. Компонент­ные архитектуры хорошо приспособлены для адаптации, так как любую компоненту можно заменить другой, более соответствую­щей потребностям пользователя. Предположим, что у нас есть компоненты на основе редакторов vi и Emacs (рис. 1.6). Пользова­тель 1 может настроить программы на использование vi, тогда как пользователь 2 предпочтет Emacs. Программы можно легко на­страивать, добавляя новые компоненты или заменяя имеющиеся.

 

 


Один из самых многообещающих аспектов внедрения компо­нентной архитектуры — быстрая разработка программ. Вы сможете выбирать компоненты из библиотеки и составлять из них, как из деталей конструктора, цельные приложения методом морфологиче­ского синтеза. Практически все продаваемые сегодня приложения Microsoft используют СОМ. Технология ActiveX этой фирмы по­строена на основе компонент СОМ. Программисты на Visual Basic, С++, Delphi и Java могут воспользоваться управляющими элемен­тами ActiveX для ускорения разработки своих приложений и стра­ниц Web. Конечно, каждому приложению по-прежнему будут нуж­ны и некоторые специализированные компоненты, но для по­строения простых приложений можно обойтись стандартными.

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

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

Чтобы понять, как это связано с инкапсуляцией, необходимо определить некоторые термины. Программа или компонента, ис­пользующая другую компоненту, называется клиентом {client). Кли­ент подсоединяется к компоненте через интерфейс (interface). Если компонента изменяется без изменения интерфейса, то изменений в клиенте не потребуется. Аналогично если клиент изменяется без изменения интерфейса, то нет необходимости изменять компонен­ту. Однако если изменение либо клиента, либо компоненты вызы­вает изменение интерфейса, то и другую сторону интерфейса также необходимо изменить.

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

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

Ограничение 1. Компонента должна скрывать используемый язык программирования. Компоненты могут быть разработаны с помощью практически любого процедурного языка, включая Ada, С, Java, Modula-3, Oberon и Pascal. Любой язык, в том числе Smalltalk и Visual Basic, можно приспособить к использованию компонент СОМ. Любой клиент должен иметь возможность ис­пользовать компоненту независимо от языков программирования, на которых написаны тот и другой.

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

Ограничение 3. Компоненты СОМ можно модернизировать, не нарушая работы старых клиентов. СОМ предоставляет стандартный способ реализации разных версий компонент. Новые версии компо­нент должны работать как с новыми клиентами, так и старыми.

Ограничение 4. Компоненты СОМ являются перемещаемыми по сети, причем перемещаемость по сети должна быть прозрачной. Компонента на удаленной системе рассматривается так же, как компонента на локальном компьютере. Необходимо, чтобы компо­нента и использующая ее программа могли выполняться внутри одного процесса, в разных процессах или на разных машинах. Клиент должен рассматривать удаленную компоненту так же, как локальную. Если бы с удаленными компонентами надо было бы работать иначе, чем с локальными, то потребовалось бы переком­пиляция клиента всякий раз, когда локальная компонента переме­щается в другое место сети.

Пользователь может иметь два клиентских приложения, ис­пользующих одну и ту же компоненту. Предположим, что одно приложение применяет новую версию этой компоненты, а дру­гое — старую. Установка новой версии не должна нарушать работу приложения, которое использовало старую версию. Старое прило­жение использует новую компоненту vi абсолютно так же, как это делает новое (рис. 1.7).

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

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

 

Выводы:

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

• Программная система может состоять из отдельных, разрабо­танных разными организациями выполняемых программ; из про­грамм, обменивающихся данными через порты; из отдельных рези­дентных программ.

• Традиционно программа проектировалась из отдельных фай­лов, модулей или классов, которые компилировались и компонова­лись в единое целое.

• Разработка программ из компонент — так называемых прило­жений компонентной архитектуры — происходит совершенно ина­че. С появлением технологии разработки развивающихся и рассре­доточенных (многомашинных) комплексов программ, основанной на модели компонентных объектов (СОМ), единого целого больше нет: программы состоят из отдельных компонент. Компонента по­ставляется пользователю как двоичный код, скомпилированный, скомпонованный и готовый к использованию. Доступ к этому коду осуществляется через точно документированный интерфейс. Во время выполнения компоненты подключаются к другим компонен­там, формируя программу.

 

ЗАКЛЮЧЕНИЕ

Кратко подводятся итоги занятия, при этом обращается внимание студентов на основные понятия процесса производства программных продуктов.

Дать задание на самостоятельную работу (отводимое время 1 час):

ó с целью более глубокого освоения материала повторить и более подробно изучить материал. Литература: [1] с. 60…76, [2] с.28...33, 207…218, конспект лекций. При необходимости ответить на возникшие вопросы.

 

Старший преподаватель кафедры автоматизированных систем и