Программная платформа для построения адаптивных приложений информационных систем

Шибанов С.В., Илюшкин А.С., Мезенков А.А., Скоробогатько А.А.

ПРОГРАММНАЯ ПЛАТФОРМА ДЛЯ ПОСТРОЕНИЯ АДАПТИВНЫХПРИЛОЖЕНИЙ ИНФОРМАЦИОННЫХ СИСТЕМ

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

Рисунок 1 - Факторы, требующие адаптации в приложениях информационных систем

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

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

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

Рисунок 2. - Взаимодействие активных приложений распределенной информационной системы

Использование событийного управления в технических и информационных системах не ново и в своё время получило достаточно широкое распространение в области активных баз данных (АБД). В современных СУБД наиболее ярким примером подобного функционала являются триггеры. Среди существующих решений в области интеграции крупных распределённых информационных систем отсутствуют комплексные подходы, совмещающие в себе достоинства как активного, так и традиционного пассивного (запросного) видов взаимодействия. Поэтому разработка методов и программных средств построения активных приложений информационных систем является весьма актуальной задачей. Предлагается выполнить расширение зоны активности с уровня АБД на остальные уровни распределённой информационной системы.

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

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

Для предоставления возможности быстрого перемещения реагирующих на события компонентов сложной распределённой системы между узлами, в качестве её основы планируется использовать единую концепцию взаимозаменяемых элементов [4]. Для этого все части системы, будь то конечные или промежуточные серверы, GUI-клиенты и службы, используют в качестве своей базы программный каркас (платформу) как ядро и расширяемый набор плагинов как оболочку. Использование единообразного интерфейса позволяет перемещать их между компонентами системы, в том числе и во время работы. Реализация управляющей платформы, а также системы плагинов для неё, будет способствовать гибкому расширению функциональности системы, решению проблем, связанных с тиражированием и синхронизацией контента, поддержкой версионности, а так же передачей сообщений и адаптации пользовательского интерфейса.

Анализ архитектур приложения на основе плагинов.Сама технология плагинов и различные ее модификации нашли достаточно широкое применение при конструировании приложений, но, тем не менее, вариантов реализации систем, использующих плагины для автоматического распространения компонентов между узлами не так уж много. Наиболее известными являются модули автоматического получения обновлений, применяемые в популярных браузерах, например, в Mozilla Firefox, или в программах быстрого обмена сообщениями, например, в Miranda IM. Так же сюда можно отнести используемые в linux-дистрибутивах системы управления пакетами, такие как APT [3], RPM, или средства, аналогичные setuptools для языка Python. Однако хотя существующие решения и позволяют разворачивать обновления компонентов на конечных узлах, они не предоставляют возможность двустороннего взаимодействия с источником обновлений средствами одних и тех же технологических приёмов. Поэтому, основной задачей является выделение преимуществ имеющихся подходов к модульной организации программных узлов и совмещение их с активной компонентой для решения проблем, связанных с тиражированием и синхронизацией контента, поддержкой версионности, а так же передачей сообщений пользовательского интерфейса. Помимо этого, существует ряд задач по обеспечению взаимозаменяемости узлов, упрощению написания модулей расширения и автоматических тестов.

На рисунке 4 изображена диаграмма компонент, иллюстрирующая типовую архитектуру приложения, использующего плагины.

Рисунок 4 - Типовая архитектура приложения на основе плагинов

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

Плагины могут быть реализованы различными способами, которые определяются, в том числе, используемыми технологиями и средствами разработки:

В виде динамически подключаемой библиотеки. Плагин оформляется в виде динамически подключаемого исполняемого модуля: DLL (Dynamic-linklibrary) в операционной системе windows, SO (Sharedobject) в операционной системе Linux. Данный подход применяется в приложениях, написанных на компилируемых языках программирования, например: Notepad++, MirandaIM, Photoshop, MicrosoftVisualStudio.

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

Рисунок 5 - Типовая архитектура приложения на основе плагинов и каркаса модульных приложений

Каркас модульных приложений содержит только средства управления плагинами и механизмы взаимодействия между ними. Вся прикладная функциональность приложения распределена между плагинами. Часть плагинов предоставляет функциональность (сервисы), другая часть их использует. Это дает возможность динамически (без перекомпиляции) создавать нужную конфигурацию приложения путем подключе-ния/отключения модулей. Кроме того, один плагин может использоваться в разных приложениях без внесения в него изменений.

Одними из наиболее известных реализаций каркасов модульных приложений являются ManagedExtensibilityFramework и Equinox.

ManagedExtensibilityFramework (MEF) - это реализация каркаса модульных приложений для платформы .NET. Каркас MEF базируется на трех понятиях - экспорт, импорт и композиция.

Экспорт - это функциональность, предоставляемая для использования в других частях приложения (в других приложениях). Аналогом понятия экспорта является термин «плагин».

Импортом называют описание части функциональности, которая не реализована в приложении и должна быть предоставлена плагинами. Другими словами, импорт является «точкой расширения».

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

Equinox является каркасом модульных приложений, написанных на языке Java. Приложение, построенное на платформе Equinox, состоит из набора пакетов (bundle). Пакет является контейнером ресурсов приложения (программного кода, настроек и т.п.). Пакеты взаимодействуют с помощью механизма «сервисов». Сервис является описанием предоставляемой функциональности. Пакеты регистрируют сервисы в ядре системы, после чего сервисы могут использоваться другими пакетами. Equinox является реализацией платформы OSGi .

Программная платформа для построения адаптивных приложений информационных систем. Программная платформа (каркас приложений) является самостоятельным программным компонентом и в самом простом случае может запускаться при полном отсутствии внешних модулей, но при этом не будет содержать никакой функциональной нагрузки, полезной для конечного пользователя. Его отличительной чертой является наличие средств (в форме API) регистрации, инициализации и динамической загрузки плагинов. По-умолчанию каркас приложений не имеет пользовательского интерфейса и работает в фоновом режиме. Для указания порядка просмотра каталогов для загрузки внешних модулей первого уровня используется xml-файл конфигурации. Имя исполняемого файла каркаса приложений и имя файла конфигурации может быть произвольным. Все изменения поведения каркаса выполняются при помощи подключаемых модулей, позволяющих переводить его, например, в режим службы, веб- или оконного приложения. Стоит особо подчеркнуть, что каркас приложения должен быть спроектирован таким образом, чтобы минимизировать возможность возникновения потребности в его обновлении на конечных точках системы после выполнения процедуры развёртывания. Распространение новой функциональности и исправление ошибок и неточностей в существующих алгоритмах должно производиться исключительно при помощи обмена подключаемыми модулями. В связи с этим нет необходимости внедрять поддержку версионности непосредственно в код каркаса приложения на этапе прототипирования.

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

Для разработки выбрана платформа Microsoft .NET, поэтому на плагины и файлы конфигурации накладываются дополнительные ограничения:

каждый плагин представляет собой библиотеку динамической компоновки (сборку), которая содержит в себе соответствующий IL-код и имеет расширение *.dll;

файлы конфигурации представляют собой текстовые xml-файлы в кодировке UTF-8, имеют расширение *.xml;

основу имени каждого плагина и файла конфигурации составляет глобально-уникальный идентификатор (GUID), в общем случае имя имеет следующий формат:

XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.{ dll | xml }.

Каждый символ «X» в данном шаблоне имени представляет собой некое число в шестнадцатеричной системе счисления. Каждая новая версия одного и того же плагина снабжается уникальным GUID, поэтому в создаваемом прототипе системы не предполагается наличие привычных числовых номеров версий в формате четырёх десятичных чисел разделённых точкой. Может показаться, что подобная система именования не очень удобна. Однако основным её преимуществом является возможность обеспечения уникальности имён плагинов, особенно это актуально при автоматическом формировании плагинов, когда информационная система достигает крупных масштабов. Кроме того, появляется возможность избавиться от хранения полного пути к файлам плагинов в файле конфигурации каркаса.

Использование дерева каталогов для хранения плагинов позволяет находить каждый плагин только по его имени. При этом путь формируется путём компоновки имён каталогов. Например, имя plugin.dll будет разложено в следующий путь ./p/l/u/g/i/n.dll. Тем самым система отображения имён плагинов на репозиторий сможет определить путь к файлу исключительно по его имени.

Файл конфигурации каждого плагина содержит информацию о событиях, которые данный модуль может обрабатывать. Такой подход необходим по причине того, что идентификаторы событий в рамках системы могут меняться без изменения логики их обработки, и поэтому не должны быть жёстко запрограммированы в код подключаемых модулей. Имя плагина одновременно является идентификатором класса событий. Этим достигается возможность обработки множества однотипных событий при помощи одногоплагина.

Рисунок 6 - Взаимодействие программной платформы приложений и плагинов

При запуске каркаса приложений им выполняется чтение собственного файла конфигурации для определения списка первоначально загружаемых модулей. Затем производится разрешение путей к плагинам в порядке их следования в файле конфигурации с последующей загрузкой. Стоит отметить, что плагины, использующие для своей работы другие плагины в качестве основы при наследовании, загружают их автоматически через зависимости (references) средствами .NET Framework, путём стандартного алгоритма разрешения ссылок на сборки. Отличительной чертой в данном случае является то, что в случае, если зависимый плагин расположен в древовидном хранилище, а не в каталоге с текущей загружаемой сборкой или глобальном кеше сборок, то работу по его поиску берёт на себя каркас приложения. Поиск в хранилище осуществляется тем же способом, что и при обнаружении других плагинов.

Так как все плагины унаследованы от одного абстрактного класса, то именно на том, является ли класс внутри загруженной библиотеки его наследником, каркас решает, является загруженная библиотека плагином или нет. Если библиотека содержит несколько классов-наследников базового для всех плагинов класса, то выбирается первый из списка имён классов, отсортированного в лексикографическом порядке. Желательно, чтобы имя класса-плагина имело постфикс Plugin, например:

public class AutomatedUpdatesPlugin : Plugin { ... }

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

Рисунок 7 - UML-диаграмма классов реализации плагинов

Для этого в метод регистрации передаётся экземпляр класса, содержащий в себе набор методов API каркаса приложений. Интерфейс IStrategy, реализуемый классом ModelManager, (рисунок 7) назовём его стратегией взаимодействия с каркасом приложений. Этот класс является общедоступным для всех плагинов и используется для регистрации плагина, подписки на события, отправки событий, благодаря которым и осуществляется взаимодействие плагина с внешним миром. Таким образом, вызов методов одного плагина из другого становится нецелесообразным, так как работоспособность плагина гарантируется только в случае наличия у него экземпляра стратегии для взаимодействия с каркасом приложений.

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

Пример реализации и использования плагина в программной платформе.Рассмотрим в качестве примера простейший случай обработки нажатия на кнопку. Допустим, имеется форма, содержащая единственную кнопку, при этом форма и кнопка расположены в двух отдельных плагинах. В целях сокращения объемов текста условимся именовать сообщение о нажатии на кнопку через символ C, событие загрузки формы через L, событие-ответ кнопки R. Итак, при загрузке плагина кнопки он вначале подписывается на зависимое событие L, затем переходит в состояние ожидания (возможен и обратный вариант, когда форма подписывается на событие создания кнопки; порядок зависит от конфигурирования каркаса приложений). Плагин формы вначале подписывается на зависимое событие R, а затем после загрузки отправляет L. При этом кнопка, получив L, отправляет в ответ R с прикреплённым экземпляром кнопки. Форма, получив R, добавляет кнопку во внутренний список элементов управление и подписывается на независимое событие C. Таким образом, все дальнейшие нажатия на кнопку, генерирующие событие C будут получены формой.

Каркас приложений содержит в конфигурационном файле следующую запись:

<?xml version="1.0" encoding="UTF-8" ?>

<Plugins>

<GUID>b4c8eaa4-d2b5-4560-a64d-cb1021a7fb56</ GUID >

</ Plugins >

Означающую, что поиск нужно выполнять в локальном хранилище плагинов, при этом глубина разложения GUID на каталоги зависит от длины идентификатора и не обязательно должна выполняться для всего имени полностью, достаточно использовать первые восемь символов имени. В этом случае полный путь внутри хранилища путь будет иметь вид /b/4/c/8/e/a/a/4/d2b5-4560-a64d-cb1021a7fb56.dll. Стоит отметить, что цепочка каталогов создаётся при регистрации конкретного модуля в каркасе, одновременно с модификацией глобального файла конфигурации. Предварительное создание структуры каталогов не целесообразно, так как общее их количество для GUID, состоящего из 32 символов и длине шестнадцатеричного алфавита равного 16 символам составит:

32

N = £ 16" = 3,62967858049001e+ 38 .

n=1

Одновременно с плагином в каталоге по адресу /b/4/c/8/e/a/a/4/ хранится файл конфигурации d2b5-4560-a64d-cb1021a7fb56.xml, имеющий следующую структуру:

<?xml version="1.0" encoding="UTF-8" ?>

<OutgoingEvents>

<Event>

<Guid>a018b13c-cd1d-4ac8-b3d1-fbe20b434c14</Guid>

</Event>

</OutgoingEvents>

Содержимое файла конфигурации показывает, что данный плагин генерирует исходящие события с идентификатором a018b13c-cd1d-4ac8-b3d1-fbe20b434c14 (для примера выбран случайно), что в сочетании с

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

Заключение.Применение модульной архитектуры при разработке активных распределённых информационных систем позволяет значительно повысить гибкость создаваемых программных продуктов, одновременно разделить на уровне архитектуры реализации отдельных алгоритмов бизнес-логики. Это дополнительно структурирует процесс разработки, упрощает создание автоматических тестов, позволяет перемещать бизнеслогику приложения между компонентами РИС во время работы. Предлагаемый подход особенно важен приме -нительно к классу активных систем, в которых динамическое изменение реакций на события позволяет

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

ЛИТЕРАТУРА

1. Шибанов С.В., Мезенков А.А. Повышение надёжности клиент-серверных приложений в информационных системах // Технологии Microsoft в теории и практике программирования. Материалы конференции. -

H. Новгород: Изд-во Нижегородского гос. ун-та 2010. - С. 286-289.

2. Шибанов С.В., Мезенков А.А., Макарычев П.П. Применение метаданных в адаптивных информационных системах клиент-серверной архитектуры // Надежность и качество: Труды международ. симпозиума, т.

I. - Пенза, Информац.-изд. центр Пенз. гос. ун-та, 2010. - с. 120-125.

3. S. Ajmani. Automatic Software Upgrades for Distributed Systems. Ph.D., MIT, Sept. 2004. Also as Technical Report MIT-LCS-TR-1012.

4. Шибанов С.В., Илюшкин А.С., Шевченко О.А., Макарычев П.П. Управление обменом информацией в распределённых информационных системах с использованием активного пакета, Надежность и качество. Труды международного симпозиума, Пенза, Изд-во ПГУ, 2010.