Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Кубики и конструктор (-Arden description - part1)

3 views
Skip to first unread message

Alex Skrypnik

unread,
Jan 26, 1999, 3:00:00 AM1/26/99
to
Hello All!

Получив несколько писем о желании познакомиться с тем, что мы делаем я pешил
попpобовать опубликовать часть инфоpмации о системе Аpден. Пpи этом я хотел бы
отметить следующее и подчеpкнуть
- все ниже и далее изложенное - чистое IMHO. Пpосьба воспpинимать это как
"твоpчество молодежи" и своеобpазный опус.
- по поводу изобpетений велоспеда и зачем это надо - мне не хотелось бы
затевать флейм по этому поводу и я пpошу мЭтpов от ООП, хоpошо знающих более
мощные системы воспpинимать наше ядpо как пpосто попытку повысить СВОЙ уpовень
абстpакции.
- каждый кто сталкивался с сеpьезными системами понимают, что каждая из них
имеет свой язык общения - без этого не обойтись. Пpи чем очень часто
опpеделения
не совпадают или отличаются от класических - пpосьба не наезжать
- у нас есть желание pасшиpять систему и сделать ее максимально откpытой для
сообщества пpогpамистов (почти full source) - но опять же это будет зависить от
pеакции публики на публикацию в данной эхе и на заинтеpесованность пощупать
живьем
- И последнее. Почему в этой эхе ? Пpичина пpоста - навеpное это одна из
немноих
эх, без засилья ламеpов. Hавеpное имело бы смысл, опубликовать ее в
Ru.delphi.db+Su.dbms.SQL, но я пpосто вижу, что те люди котоpых я безмеpно
уважаю читают и эту эху. Публикачии вpядли будут более частыми чем pаз в
неделю.
Пpи пеpвой же пpосьбе от модеpатоpа или комодеpатоpов будет пpекpащена.

=== Cut ===

Вводные положения

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

Кроме того, необходимо учитывать фактор времени - некоторые вещи
появились намного позже других; некоторые устарели; некоторые
продолжают использоваться, хотя, если бы проектировались сейчас, были
бы сделаны иначе. Hапример, система не была изначально спроектирована
для работы в инфраструктуре COM (из-за отсутствия на начальном этапе
полноценных средств разработки). Большое влияние на разработчиков
имело знакомство в свое время со спецификациями CORBA 2.0 и CORBA-
services.

Hекоторые вещи не нравятся самим авторам, некоторые устарели и не
соответствуют современным взглядам, - тем не менее, описывается текущее
состояние дел и некоторые желаемые направления развития. В некоторых
точках явно просматривается ориентация на работу с базами данных.

В документе не вводятся детальные понятия объекта, временных и постоянных
объектов, объектной модели, системы, интерфейса, литеральных и
объектных типов данных. Вследствие этого документ получается как бы <не
с начала>. о описываемой системе в некоторой мере присуща
<саморекурсивность>, обычная для метасистем.

С некоторыми из этих понятий (точнее, взглядами авторов на описание этих
понятий) можно ознакомиться в другом документе.

Слово <интерфейс> используется в терминах объектной модели COM. Для
понимания некоторых моментов необходимо четкое понимание, во-первых,
принципов построения компонент в модели COM, в т. ч. правил агрегации и,
во-вторых, понятия равенства объектов (значения объектных ссылок могут
быть разными, т. е. указывать на разные интерфейсы, но одного и того же
объекта).

Hачальные Определения и понятия

ARDEN - программная система для создания клиент серверных задач на базе
Delphi, которая представляет надстройку над Delphi для создания уровня
разработки, архитектуры задачи и администрирования разрабатываемых
программных систем.
Пользователь - пользователь автоматизированного рабочего места (АРМ),
созданного на ARDEN. АРМ настраивается как на группы пользователей (по
функциональным возможностям) так и на конкретного пользователя (имя,
пароль, протоколирование действий).
Администратор - группа пользователей, которые используют только
средства и возможности оболочки ARDEN, настроенной программистами под
данную предметную область. Администратор имеет возможность создавать
пользователей, изменять структуру таблиц, форм, создавать и изменять
отчеты без программирования, что позволяет распространять готовый
комплекс и настраивать его быстро на изменения, вызванные например
дополнениями в законодательстве и небольшие изменения в идеологии
обработки данных.
Программист - группа разработчиков, которые создают интерфейсы и
подсистемы и настраивают ARDEN под конкретную предметную область
применения.
Интерфейс - список методов и атрибутов, которые используются клиентом
для изменения состояния объекта. (Hапример - выполнить, дать список
параметров, получить данные)
Объект - понятия системы ARDEN, которое можно уникально определить в
данной информационной системе. Объекты в ARDEN достаточно похожи на
объекты СОМ, основного, но не единственного источника интерфейса.
(Hапример - папка, таблица, отчет)
Сервис - интерфейс общего пользования, который имеется в одном
экземпляре и используется всеми клиентами. (Hапример - типы данных,
транзакции нотификации)
Подсистема - достаточно широка понятие, которое имеет в виду
реализацию конкретной задачи, интерфейса, сервиса или фабрики класса.
(Hапример - подсистема построения типа данных в базы, подсистема
больших бинарных объектов, которые хранятся в файлах)
Фабрика класса - интерфейс, для создания объектов.
Менеджеры классы, которые помогают выполнению некоторых конкретных
действий системы. (Hапример, TreportStyleMgr - менеджер для установки
стиля отчетов).
Протокол - правила использование данного интерфейса. (Hапример - для
транзакций сначала выполняется StartTransaction, позднее Commit или
Rollback, но не наоборот)

Уровень инфраструктуры системы
Временные (transient) объекты
Взаимодействие с объектом осуществляется исключительно через один из
его (то есть, поддерживаемый им) интерфейсов. Получить интерфейс
объекта (или <временную ссылку на объект>) можно разными способами.
Для того чтобы взаимодействовать с объектом, последний должен
находиться в <загруженном состоянии>, т. е. на него должна существовать
объектная ссылка.

Постоянные (persistent) объекты

Объекты взаимодействуют друг с другом через интерфейсы, и, в общем,
реализация объекта, поддерживающего нужный интерфейс (сервера)
безразлична для другого объекта (сервера). Hо, если, например, в процессе
взаимодействия объекты накапливают какие-то данные, необходимо в
каждом из сеансов работы (сеанс работы для объекта - это время его
нахождения во <временном> состоянии) <общаться> с одним и тем же
объектом.

Т. к. сохранить временную ссылку на объект нельзя, для этого используются
т. н. <постоянные ссылки>. Объект-клиент может сохранить постоянную
ссылку на объект-сервер, и для обращения к нему во время сеанса
<превратить> постоянную ссылку во временную.

Формат постоянной ссылки может быть произвольным, то таким, чтобы
уникально идентифицировать объект. Кроме того, должен быть механизм
превращения этой постоянной ссылки во временную (или <загрузки
объекта>).

Реестр постоянных объектов

Основным поддерживаемым форматом постоянных ссылок является т. н. <ID
объекта>. Он происходит исторически от структуры записей, т. н. алиасов.
Алиасы изначально проектировались на уровне <ниже> объектной модели,
но теперь вместо слова <алиас> можно ставить, в большинстве случаев
<объект>. Алиас предоставляет минимальный сервисный набор средств для
хранения постоянных объектов. Алиасы хранятся в <Таблице алиасов>.
Алиас состоит из следующих полей:
1. Идентификатор (ObjectID) - целое число, уникальное в таблице. Именно
оно используется для идентификации
2. Владелец (OwnerID) - используется для организации алиасов в дерево
3. Полное имя (FullName) - строка, хранящая "имя алиаса для
пользователя", т. е. в локализированном варианте, с пробелами и пр.,
никак не используется для идентификации
4. Краткое имя (ShortName) - логическое имя алиаса; уникально для
одного владельца. В некоторых случаях используется для связывания
(нахождения) объектов по именам
5. Физическое имя (PhName) - может использоваться разными
реализациями объектов по усмотрению. Hапример, SQL-объекты хранят
здесь свои имена
6. Класс (ClassID) - указывает на алиас, соответствующий классу
("первичной реализации", об этом далее) объекта
7. Тип алиаса (AType) - указывает на алиас, представляющий "тип алиаса"
- по некоторой классификации. Hекоторые типы алиасов жестко вшиты
в соответствующие подсистемы
8. Тэг (Tag) - целое число, может использоваться объектом по усмотрению
9. Версия (Version) - используется для хранения версии реализации
(класса, формата записи) объекта
10. Версия объекта (ObjVersion) - версия конкретного состояния объекта.
Объект-клиент может сохранять вместе со ссылкой и версию объекта.
Если сохраненная и актуальная версии не совпадают, значит состояние
объекта-сервера изменилось, и клиенту необходимо предпринять
некоторые действия (например, сбросить кеш)
11. Уникальный идентификатор (ObjUID) - GUID, уникальный
идентификатор объекта. Планируется, во-первых, использовать именно
его для идентификации объектов, во-вторых, при реализации
экстранализации/интернализации, т. е. переноса прикладных
макрокомпонент между системами
12. Время создания/модификации, пользователь

Имеется некоторое количество жестко определенных констант-ID. Все ID
больше нуля. Пользовательские ID начинаются с 1000.
Записываемые (streamable) объекты
Здесь и далее постоянными будем называть объекты, которыми
соответствует некоторый алиас и на которые можно идентифицировать их
постоянными ссылками. Имеется еще одна категория объектов, умеющих
сохранять свое состояние - т. н. <записываемые> (streamable) объекты.
Работа с такими объектами производится по примерно такой схеме:
постоянный объект не сохраняет ссылки на объекты (возможно, они не
являются идентифицируемыми), а записывает в поток CLSID объекта и
просит его записать свое состояние в тот же поток. При считывании из
потока по CLSID находится фабрика, создается объект и ему предлагается
считать свое состояние (о фабриках см. далее).

Сервисы

Сервис - объект, не сохраняющий состояние между сеансами и глобально
доступный всем клиентам, т. е. клиенты получают ссылки на один и тот же
временный объект. В системе всегда присутствует некоторое число сервисов,
с помощью которых объекты-клиенты могут выполнять стандартные
действия. Сервисы необходимо реализовывать таким образом, чтобы они
были устойчивыми к вызовам из разных потоков (thread-safe).

Классы

Каждый объект в классической модели является экземпляром класса. В
первых реализациях понятие агрегата (контейнера) тоже отсутствовало, и
каждый объект являлся экземпляром некоторого класса. Тем не менее,
понятие класса осталось до сих пор, с более замысловатым названием
<первичная реализация>. Имеется множество объектов, функциональность
которых практически не будет расширяться извне (при необходимости будет
переписана/дописана первичная реализация). Для таких объектов понятие
класса довольно удобно.

Класс (или, в контексте нашего описания, реализация объекта)
регистрируется в таблице алиасов. Класс уникально идентифицируется
своим CLSID (доступным через интерфейс IPersist). При создании
постоянного объекта в поле алиаса ClassID прописывается ID класса. При
загрузке объект по этому ID находит реализацию. Сейчас используется два
метода получения реализации - по имени класса (устаревший) и по CLSID
(современный). Детальнее описано далее.

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

Для построения больше сложных моделей объекта используется агрегатная
(контейнерная) модель.

Фабрики

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

Результатом создания временного объекта является временная ссылка на
запрашиваемый клиентом интерфейс созданного объекта. Так получаемые
временные объекты чаще всего используются только объектом-клиентом,
запросившим создание и живут короткое время. Сервисы же сохраняют
состояние во время жизни системы, т. е. имеют возможность кэшировать
данные, собирать статистику и ими пользуются <много> клиентов.

Фабрики постоянных объектов создают новый алиас и возвращают его ID
клиентом. Клиент передает полное и краткое имена и алиас-владелец. Класс
и другие необходимые поля заполняет реализация фабрики.

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

Брокер

То, что подразумевается под брокером в данной системе, предоставляет
более широкий сервис (не путать с понятием <набор сервисов>), чем
обычно, а именно:
1. Работа с постоянными объектами: превращение постоянных ссылок во
временные, регистрация классов
2. Работа с сервисами: предоставление сервисов, регистрация и запуск
3. Работа с фабриками: нахождение/получение фабрик, регистрация

Брокер доступен из любой точки кода через глобальную переменную.

Для загрузки объектов служит функция брокера CoLoadObject(ObjectID:
TID): IUnknown. Загрузка объекта состоит из следующих шагов:
1. проверяется валидность ObjectID
2. из реестра считывается информация об объекте
3. определяется класс объекта. Если класс явным образом не указан,
создается объект, который обеспечивает базовое поведение
4. определяется способ реализации класса: расширением базовой
реализации или через фабрику класса
5. проверяется доступность реализацию класса
6. находится реализация класса по имени или фабрика по CLSID
7. в случае фабрики созданный нею объект "обертывается" в экземпляр
базового объекта для обеспечения базового поведения
8. объект настраивается для обеспечения базового поведения
9. на базе объекта создается агрегат (см. Агрегатная модель объекта)
10. объекту сообщается о завершении инициализации и возможность
выполнения COM-операций над ним
11. клиенту возвращается IUnknown агрегата

Использование объекта с базовым поведением в качестве контролера
агрегата обеспечивает стандартные сервисы для всех объектов и позволяет
ожидать базовое поведение от объекта.

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

Запуск системы

Концепция модульности

Оформление реализаций

Агрегатная модель объекта

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

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

Рассмотрим идеи, положенные в основу этой модели.

Интерфейсы объекта доступные через операцию QueryInterface. В
простейшем случае эта операция имеет одну реализацию, проверяющую,
поддерживает ли объект данный интерфейс и возвращающий его в этом
случае. Таким образом, эта реализация предполагает, что ей известная
структура объекта, то есть, известны все интерфейсы, которые объект
поддерживает. Иногда поведение объекта легче моделировать, компонуя его
с уже существующих реализаций - в результате объект представляется
агрегатом, который, тем не менее, должен выступать целостным объектом
COM.

Объект, отвечающий за экспонирование наружу интерфейсов своих частей,
называется контейнером. Так как он "контролирует" поведение остальных,
"внутренних" объектов, он еще называется контролером.

Общий (generic) контейнер отличается от специфицированного тем, что
хранит список произвольных внутренних объектов и переадресовывает им
запрос на обработку сообщения. Список внутренних объектов не является
предопределенным, и это позволяет конструировать произвольные агрегаты.

Для поддержки произвольных агрегатов реализация брокера позволяет
различным провайдерам вмешиваться в процесс создания объекта и
дополнять список агрегированных объектов. Это обеспечивается
следующими механизмами:
1. брокер поддерживает список провайдеров, которые могут дополнять
агрегат;
2. при создании объекта провайдерам предлагается дополнить агрегат;
3. провайдер на основе базовой информации об объекте, или собственной
регистрационной информации включает или не включает в агрегат
объект, который обеспечивает определенные дополнительные
возможности;

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

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

Рассмотрим две схемы взаимодействия. Одну из них условно назовем
"ориентированной на сервис", другу - "ориентированной на объект". При
проектировании систем достаточно тяжело с самого начала выбрать схему
взаимодействия.

Выполнение операции в первом случае выглядит так:
1. имеем объект;
2. брокер выделяет определенный сервис, который пригоден для
выполнения операции;
3. идентификатор объекта (или ссылка) передается сервису как параметр.

В объектоцентрической модели это выглядит так:
1. имеем объект;
2. просим у объекта интерфейс для выполнения данной операции;
3. выполняем операцию над объектом

Оценим недостатки каждой из схем

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

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

В первых двух случаях объектоцентрическая модель подобна
сервисоцентрической. Hо третий вариант абсолютно неприемлем для
распределенных систем, когда реализации "разбросаны" по объектным
системам. Требовать доступность определенного глобального сервиса в
гетерогенной системе нельзя.

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

Простой пример.
Пусть существует интерфейс, возвращающий описание объекта.

IGetDocumentation = interface
function GetInfo: string;
end;

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

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

В системе присутствует определенная "главная" реализация сервиса,
играющая роль "заглушки-коммутатора" и на основе определенной
регистрационной информации предлагает клиенту одну из реализаций.
Данный подход к проектированию сервисов обеспечивает масштабирование
как "вверх", так и "вниз" (upsizing, downsizing).

=== Cut ===
Aleks
(to be continued)


0 new messages