Евгений Игумнов
Введение
Полученную мною спецификацию каркаса системы с распределенной архитектурой (distributed framework - dfw) можно использовать как отправную точку при создании корпоративных распределенных систем. Предлагаемая спецификация не зависит от распределенной технологии, на основе которой будет построена система. Другими словами, предлагаемая спецификация может быть использована совместно с технологиями RMI, CORBA, DCOM и др. Проблемы реализации интеграции с этими технологиями не рассматриваются. Они ложатся на разработчиков, решивших использовать эту спецификацию. Спецификация была получена при анализе трех типов систем: OLTP, OLAP и GIS. Каркас системы направлен на объектно-ориентированный язык и в основе своей содержит набор шаблонов проектирования для высокого повторного использования.
1. Общая компонентная модель
Система состоит из трех частей: клиентское приложение (GUI или Web), сервер приложений и источник данных (СУБД, XML и т.д.). Идеология системы строится на трех вещах: фактах, метамодели и безопасности. Факты- это так называемые бизнес-объекты из предметной области, с которой будет работать система. Метамодель - это описание этих бизнес-объектов. Безопасность - это описание прав доступа к фактам и метамодели. Диаграмма пакетов системы изображена на рис. 1.1. Следует обратить внимание на функциональную значимость метамодели в этой системе. Обычно при реализации большого количества типов бизнес-объектов (фактов) для каждого факта ставится в соответствие класс. Для того, чтобы повысить степень повторного использования и упростить механизм поддержки большого числа типов фактов в системе, следует для всех фактов выделить всего один или два класса, а структуру фактов описать в метамодели. Таким образом, при изменении структуры фактов не нужно будет менять исходные коды, а достаточно будет поправить информацию в источнике данных, например СУБД, откуда берет данные метамодель.
Рис. 1.1 Диаграмма зависимости между пакетами
Клиентская часть состоит из 10 пакетов. Пакет view отвечает за ее внешний вид. Пакет mediator сопрягает виды приложения. Пакет model отвечает за внутреннее представление данных приложения. Пакет controller содержит классы, работающие с моделью данных приложения. Пакет model.fact представляет структуры фактов, которыми обменивается клиентское приложение с сервером приложений. Пакет model.meta представляет структуры описывающих факты, т.е. метамодель, которыми обменивается клиентское приложение с сервером приложений. Пакет model.security представляет структуры, описывающие безопасность доступа к фактам и метамодели, которыми также обменивается клиентское приложение с сервером приложений. Пакеты source.fact, source.meta и source.security отвечают за взаимодействие между клиентским приложением и сервером приложений и поддерживают между ними обмен фактами (model.fact), метаданными (model.meta) и безопасностью (model.security) не зависимо от используемой разработчиком распределенной технологии. Другими словами, на основе них следует делать стабы (stub) [2].
Сервер приложений состоит из 9 пакетов. Пакеты model.fact, model.meta, model.security такие же, как на стороне клиентского приложения. Они служат value-объектами обмена информацией между сервером приложений и клиентским приложением. Пакеты source.fact, source.meta и source.security на стороне сервера отвечают за взаимодействие между клиентским приложением и сервером приложений. Другими словами, на основе них следует делать скелетоны (skeleton) [2]. Пакет server.datasource отвечает за поддержку разных типов источников данных, в которых хранятся факты. Пакет server.factdao отвечает за взаимодействие с фактами для разных типов источников данных. Пакет server.kernel управляет функционированием сервера приложений, связывая воедино все пакеты серверной части.
В роли источника данных, как уже говорилось, может выступать СУБД или другое решение для доступа и хранения данных. Скорость работы с источником естественно зависит от его типа. В пакете server.factdao скорость можно поднять, например, за счет стратегии кэширования.
2. Концептуальная модель сервера
Сервер приложений состоит из так называемых заводов, которые управляют объектами в памяти сервера. Заводы представляют собой классы, построенные на основе шаблонов проектирования Singleton, Factory Method, Flyweight и Facade [1]. Шаблон Singleton предназначен для существования всего одного объекта завода в памяти сервера приложения, в котором содержатся ссылки на объекты, управляемые им. Шаблон Factory Method используется для того, чтобы только завод занимался созданием объектов, а по шаблону Flyweight в случае повторного запроса на такой же объект не производились бы затраты ресурсов сервера на повторное создание клона объекта, а изымался уже готовый объект из пула объектов. Хочу обратить внимание на то, что создание объектов обычно сопряжено с процессом считывания информации из таких источников данных, как, например СУБД.
В сервере приложений присутствует три завода. Завод MetaFactory работает с объектами, представляющими метамодель. Завод FactDAOFactory управляет объектами, которые работают с фактами. Завод SecurityFactory управляет объектами, описывающими безопасность системы. Заводы изображены на рис. 2.1.
Рис. 2.1 Концептуальная модель сервера
Сервер приложения имеет интерфейсы, через которые с ним можно взаимодействовать. Таких интерфейсов тоже три. Интерфейс FactSourceInterface предназначен для доступа к фактам. Интерфейс MetaSourceInterface предназначен для доступа к метамодели. Интерфейс SecuritySourceInterface предназначен для доступа к безопасности системы. При работе с этими интерфейсами данные заворачиваются в value-объекты, которые берутся из model.fact, model.meta и model.security соответственно. Реализуют эти интерфейсы абстрактные классы AbstractFactSource, AbstractMetaSource и AbstractSecuritySource, которые можно переопределить и делегировать вызовы со стороны клиентского приложения от скелетонов (skeleton). Классы AbstractFactSource и AbstractMetaSource в своей работе используют SecurityFactory, так как в них инкапсулированы механизмы проверки прав доступа к фактам и метамодели.
2.1. Пакеты модели метамодели, фактов и безопасности
Пакет model.meta на рис. 2.2 содержит классы, описывающие метамодель предметной области, с которой работает система. Мной было выделено всего три основных класса для этой цели. Безусловно, ее необходимо расширять для каждой специфической предметной области. Класс MetaModel предназначен для того, чтобы держать в одной системе несколько метамоделей. Класс FactDescription описывает факты. Класс Group выступает в роли тематического классификатора фактов, который всегда присутствует в информационных системах и может быть также расширен.
Рис 2.2 Модель метамодели
Пакет model.fact на рис. 2.3 имеет всего один класс Fact, объекты которого будут фактами. Этот класс следует, безусловно, расширить, так как встреченные мной факты из разных предметных областей имеют общее только то, что они являются фактами.
Рис. 2.3 Модель фактов
Пакет model.security на рис. 2.4 описывает права доступа к системе, к фактам и метамодели. За основу взято классическое решение безопасности. Есть пользователи (класс User), которые сопоставлены с ролями (класс Role), имеющими права доступа (класс Access) на метамодель, которая также описывает факты. Соответственно, отсутствие прав доступа на описание факта отсекает доступ на сам факт. В процессе аутентификации участвует класс User, а в процессе авторизации - классы Role и Access соответственно.
Рис. 2.4 Модель безопасности
2.2. Пакет источников данных
Пакет server.datasource на рис. 2.5 обеспечивает связку между источниками данных и фактами. Другими словами, здесь описывается, в каком источнике данных находится какой факт. Вводится понятие картриджа (класс FactCarttridge), представляющего источник данных, в котором хранятся факты. Для работы с конкретным типом источником данных картридж использует интерфейс FactDAOInterface. Данный подход позволяет серверу приложений, с одной стороны, хранить свои факты в разных источниках данных, а с другой, не заботиться клиентскому приложению о том, как они хранятся и как расположены физически, что облегчает клиентскую часть системы.
Рис. 2.5 Источник данных
2.3. Пакет доступа к фактам
Пакет server.factdao на рис. 2.6 отвечает за работу с фактами для разных типов источников данных. За основу берется интерфейс FactDAOInteface, задающий принципы работы с фактами. Его необходимо реализовать для всех типов источников данных, которые будут подключены к системе. При реализации данного интерфейса в случае, когда некоторые источники данных имеют общие черты, следует использовать Template Me
Рис. 2.6 Доступ к фактам
2.4. Пакет ядра
Пакет server.kernel на рис. 2.7 представляет собой набор заводов FactDAOFactory, MetaFactory и SecurityFactory, управляющих моделями пакетов model.fact, model.meta и model.security, которые были описаны выше. Классы AbstractMetaSource и AbstractFactSource в своей работе используют безопасность, т.е. пользуются услугами SecurityFactory. Основная функциональная нагрузка ядра ложится на классы AbstractFactSource, AbstractMetaSource и AbstractSecuritySource, но процесс управления объектами моделей model.fact, model.meta и model.security делегируется классам FactDAOFactory, MetaFactory и SecurityFactory с использованием шаблона Adapter.
Рис. 2.7 Ядро системы
2.5. Пакеты источников метамодели, фактов и безопасности
Пакет source.meta на рис. 2.8 представляет собой интерфейс MetaSourceInterface с поддерживающим его заводом по шаблону Factory Method, который предоставляет клиентскому приложению Proxy-объект этого интерфейса по шаблону Proxy. Как уже говорилось выше, на стороне клиентского приложения реализуют этот интерфейс в виде стаба (stub), а на стороне сервера приложения - в виде скелетона (skeleton).
Рис. 2.8 Источник метамодели
Пакет source.fact на рис. 2.9 построен по таким же принципам, как пакет source.meta.
Рис. 2.9 Источник фактов
Пакет source.security на рис. 2.10 построен по таким же принципам, как пакет source.meta.
Рис. 2.10 Источник безопасности
3. Концептуальная модель клиента
Клиентское приложение на рис. 3.1 построено на основе популярного шаблона Модель-Вид-Контроллер (Model-View-Controller) [1]. Моделью служит абстрактный класс Model, который необходимо расширить для разных типов моделей, присутствующих в клиентском приложении. В роли Вида выступает абстрактный класс View, который соответственно необходимо переопределить для имеющихся видов в клиентском приложении. В роли контроллера выступает интерфейс Command, который необходимо реализовать в командах, производящих действия над Моделью на основе событий, приходящих в Вид от пользователя. Также применяется шаблон Mediator, выступающий в роли посредника между взаимосвязанными Видами. Клиентское приложение взаимодействует с сервером приложений через такие интерфейсы, как FactSourceInterface, MetaSourceInterface и SecuritySourceInterface.
Рис. 3.1 Концептуальная модель клиента
3.1. Пакет вид
Пакет client.view на рис. 3.2 представляет собой набор классов со ссылками на объекты из пакета client.model. Другими словами, Вид строится на основании Модели. Для того, чтобы ослабить их сцепленность (coupling), взаимосвязь между связанными Видами, используется ссылка на посредник класс Mediator, которому делегируются события, приходящие из внешнего мира от пользователя. В случае, когда есть уже готовый инструментарий для построения приложения, следует применять шаблон Adapter при адаптации имеющихся компонентов Видов. В случае, когда приходится самостоятельно реализовывать обвязку API, следует обратить внимание на шаблоны Composite, Decorator. Chain of Responsibility и Observer.
Рис. 3.2 Пакет вид
3.2. Пакет модель
Пакет client.model на рис. 3.3 содержит классы Модели, которые отображаются классами Вида из пакета client.view. В случае, когда есть уже готовый инструментарий для построения приложения, приходится адаптировать имеющиеся Модели из пакетов client.model.fact, client.model.meta и client.model.security с помощью шаблона Adapter к имеющимся моделям.
Рис. 3.3 Пакет модель
3.3. Пакет посредник
Пакет client.mediator на рис. 3.4 содержит класс Mediator, в роли которого может выступать главный класс приложения с методом main(). Обычно в сложных клиентских приложениях присутствует несколько расширяющих его классов.
Рис. 3.4 Пакет посредник
3.4. Пакет контроллер
Пакет client.controller на рис. 3.5 содержит интерфейс Command, который описывает стандартный способ инициирования команд, наследуемых от этого интерфейса. В этом пакете содержится классы, содержащие бизнес-логику, которая манипулирует моделью.
Рис. 3.5 пакет контроллер
4. Пример функционирования распределенной архитектуры
Описанная выше картина представляет собой функционально-ориентированный взгляд на систему и имеет статический характер. Для получения динамической картины работы всей системы следует обратить внимание на диаграмму кооперации на рис. 4.1.
Рис. 4.1 Функционирование системы
На данной диаграмме умышленно опущены детали и моменты ветвления потока управления системы для того, чтобы выделить главную идею работы, не погружаясь в детали. Распишу событийную модель по шагам:
Пользователь воздействует на Вид (View) клиентского приложения.
Вид делегирует событие Посреднику (Mediator).
Посредник обращается к Заводу (FactSourceFactory), чтобы тот создал Proxy-объект, поддерживающий интерфейс FactSourceInterface для работы с фактами.
Медиатор вызывает Контроллер (Controller) который отвечает за обработку данного типа события пришедшего от пользователя.
Контроллер посылает запрос к созданному Proxy-объекту на 3 шаге.
Proxy-объект, поддерживающий интерфейс FactSourceInteface, делегирует запрос к Источнику Фактов (AbstractFactSource) в ядре, находящемуся на стороне сервера приложения. На этом шаге происходит сетевой вызов, который проходит через стаб (stub) клиентского приложения и скелетон (skeleton) сервера приложения, где реализуется взаимодействие на одной из технологий RMI, CORBA, DCOM или др.
На стороне сервера происходит аутентификация с помощью завода, отвечающего за безопасность (SecurityFactory). Процесс аутентификации происходит только при первом обращении клиентского приложения к серверу приложений.
Происходит процесс авторизации, во время которого выясняются права доступа пользователя.
Ядро запрашивает Метамодель (MetaModel) у Завода Метаданных (MetaFactory) для описания факта, с которым взаимодействует пользователь.
Завод Метаданных извлекает запрашиваемую Метамодель.
Ядро запрашивает Метамодель на предмет Картриджа (FactCartridge), в котором находится факт.
Метамодель берет Картридж, в котором находится искомый факт.
Для доступа к фактам для разных типов источников данных ядро запрашивает у Картриджа объект, поддерживающий интерфейс FactDAO.
Картридж запрашивает этот объект у Завода Доступа к Фактам (FactDAOFactory), который создает эти объекты.
Завод Доступа к Фактам создает запрашиваемый объект.
Ядро делегирует объекту запрос от Контроллера клиентского приложения.
Объект, поддерживающий интерфейс FactDAO, производит изменения факта (Fact).
Управление возвращается в Контроллер клиентского приложения, производящий коррекцию Модели (Model).
Медиатор посылает сообщение об обновлении Модели Виду, и он производит свою перерисовку.
5. Сложность реализации
Предложенная мной спецификация имеет точки соприкосновения со спецификацией EJB в плане целей, но не содержит ограничения на архитектуру безопасности, бизнес-объектов и их описаний. Спецификация не имеет узкую направленность на конкретную распределенную технологию, такую как RMI, и определяет архитектуру клиентских приложений, чего нет в спецификации EJB. Использование уже готовых реализаций спецификации EJB очень привлекательно по сравнению с самостоятельной реализацией, предложенной мной спецификации, но в силу своих ограничений может быть отвергнута. Для получения первой версии реализации спецификации каркаса системы с распределенной архитектурой было затрачено шесть месяцев группой программистов из 6 человек с 8 часовым рабочим днем и 5 дневной рабочей неделей. Для тех организаций, которые решили воспользоваться данной спецификацией, следует предварительно просчитать все плюсы и минусы ввязывания в данную разработку.
6. Благодарности
Выражаю свою благодарность людям, которые имели прямое отношение к реализации спецификации и внесения в нее своих поправок: Алексей Неупокоев, Юрий Юдин, Роман Камерлох, Тарас Улахович, Геннадий Пестунов, Иван Пономаренко. Без участия этих людей данная спецификация никогда бы не была мной получена.
Список литературы
Гамма Э. Приемы объектно-ориентированного проектирования (паттерны проектирования). - Санкт-Петербург: Издательство «Питер», 2001. – 368с.
Цимбал А. Технология CORBA для профессионалов. – Санкт-Петербург: Издательство «Питер», 2001. – 624с.