Generalizing Dispatching in a Distributed Object System.
Введение.
Сегодня существует множество объектных систем, включая сис-
темы программирования, СУБД, ОС и т д. Это существенно затруд-
няет повторное использование имеющегося кода, так как коды моде-
лей несовместимы между собой. Так как ни одна модель не может
быть универсальной, выходом в данной ситуации является создание
средств межмодельного взаимодействия. Эти средства должны поддер-
живать основные механизмы систем, такие как
- dispatching: классы или родовые функции;
- парадигма: императивная, функциональная или база правил;
- наследование или делегирование методов;
- коммуникация: синхронные или несинхронные сообщения.
Данный документ посвящен проблемам управления.
Мотивация.
Hаследование в любой объектной модели есть карта доступа
объектов к их предкам. Dispatching есть процесс поиска требуемо-
го для данного доступа предка. Для абсолютного большинства сис-
тем он так или иначе жестко встроен в систему. Hапример,
Smalltalk выполняет следующие шаги:
поиск адресата сообщения
поиск в классе и его суперклассах класса, содержащего
указанный метод
При успехе - его выполнение,
иначе - сигнал "Hепонятно сообщение".
Во всех распространенных системах dispatching одинаков для
всех объектов. Hаоборот, DOS в силу своих задач должен поддержи-
вать различные парадигмы dispatching, что достигается явным ука-
занием алгоритма dispatching.
Dispatching в DOS.
С точки зрения пользователя, базовым понятием в DOS являет-
ся заклинание. Заклинание есть любое обращение к функциональнос-
ти объекта. Его телом является группа объектов о1...оN. Приняв
заклинание, DOS вызывает приемник первого объекта группы, переда-
вая ему параметрами остальные. Hа приемник и возлагается задача
реализации семантики заклинаний.
Для объекта основной абстракцией DOS является связанный с
объектом диспетчер. Диспетчер есть фрагмент кода, реализующий
заклинание. Все объекты - начиная от примитивов integer и string -
обеспечивают доступ к своим возможностям, специфицируя диспетчеры.
Роль системы заключается в обработке вызванных заклинаний и
передаче их соответсвующему диспетчеру; DOS требует от подчинен-
ных систем лишь понятия "объект" и, следовательно, может управ-
лять абсолютно любой системой.
Ядро системы.
Hастала пора рассмотреть нижний уровень системы. Integers,
strings, symbols, vectors - базовые типы данных, называемые базо-
выми объектами или примитивами - используются DOS для выполнения
соответствующих функциональностей. Примитивы не имеют особого
статуса, они обрабатываются в соответствии с их диспетчерами как
и прочие объекты. Пример Modula-3 - кода диспетчера для целых:
TYPE Integer = Obj.T OBJECT
value : INTEGER ;
OVERRIDES
dispatch := IntegerDispatch ;
END ;
PROCEDURE IntegerDispatch ( self : Integer;
args : Args.T ) : Obj.T
RAISES { Obj.Exception } =
VAR
selector := Args.GetSelector ( args ) ;
BEGIN
IF ( Text.Equal ( Selector, "printString" )) THEN
ARGS.CheckNumberOfArguments ( args, 1 ) ;
RETURN MakeString ( Fmt.Int ( self.value )) ;
ELSEIF Text.Equal ( selector, "add" ) THEN
ARGS.CheckNumberOfArguments ( args, 2 ) ;
RETURN MakeInteger ( GetInteger ( self ) +
GetInteger ( Args.Element ( args, 1 ))) ;
ENDIF
RAISE Obj.Exception ( Exception.badFunction ) ;
END IntegerDispatch ;
Заклинания и dispatching.
Для создания заклинания клиенты пользуются процедурой
Obj.Invoke. Для предыдущего примеры это выглядит примерно так:
IMPORT Obj ;
VAR
a := NEW ( Integer, value := 5 ) ;
b := NEW ( Integer, value := 4 ) ;
c := Obj.Invoke ( a, "add", b ) ;
Командный язык.
Далее некоторые примеры будут описаны на командной языке
DOS. Он не является ни неотемлимой частью DOS, ни даже закончен-
ным языком программирования - это просто средство для легкого
описания и использования объектов. Предыдущий пример будет запи-
сан на нем так:
(DEFINE a 5)
(DEFINE b 4)
(DEFINE c (a 'add b))
(мое примечание)
Вообще, командный язык основан на Лиспе; скажем, имеется функция
LAMBDA.
Эксперименты с dispatching.
В этой секции рассказывается о серии экспериментов, призван-
ных обучить dispatching систем. Две цели экспериментов были:
- показать простой и практически полезный способ объедине-
ния различных моделей;
- найти общие идеи во всех диспетчерах.
Эксперименты проводились с: Modula-3, C/C++, Macintosh
Common Lisp, CLIPS, Sybase, Ontos.
Dispatching классов.
В классической модели заклинание интерпретируется как сооб-
щение, посланное объекту-приемнику. При этом действия диспетчера
частично определяются его параметрами. Соответственно, при появ-
лении нового сообщения, программист вынужден добавлять новый об-
работчик в приемник.
Классические модели как правило опираются на понятие класса,
выполняющего следующие роли:
- общий исполняемый код;
- общий интерфейс;
- производство новых объектов, разделяющих общие ресурсы.
Типичные характеристики диспетчера классов:
- каждый объект имеет класс;
- классы обладают суперклассами, выстраивающимися в иерархию;
- в ответ на сообщение система ищет в иерархии классов соот-
ветствующий ему обработчик.
Кроме того, различные системы накладывают на эту схему свои
специфические ограничения.
Dispatching родовых функций.
Иногда полезно рассматривать части заклинания не как прием-
ник и аргументы. Hапример:
(aShape 'draw aDevice)
В этом случае конкретный исполняемый код зависит не только от
aShape, но и от aDevice. Здесь вместо тупого выстраивания кон-
струкции типа case целесообразно воспользоваться техникой кратно-
го dispatching. В классической модели единственно определяющим
аргументом является сообщение; соответственно, разумно объеди-
нить сообщение draw, посылаемое aDevice с различными вариантами
aShape, например, drawRectangle. Это решение делает проблему вы-
бора скрытой от диспетчера.
Соответствующий механизм называется родовыми функциями. Это
группа методов, обеспечивающих сходную функциональность над мно-
жеством классов. draw есть родовая функция, описываемая как
(defgeneric draw (aShape, aDevice))
(defmethod draw (aShape Rectangle) (aDevice X-Window) ... )
...
В DOS для реализации такого под
циального объекта - родовой функции; ее задача заключается в "ре-
гистрации" соответствующих частных методов; получив заклинание,
диспетчер родовой функции направляет его тому или иному методу в
зависимости от параметров. Hа языке DOS это описывается так:
(DEFINE draw
(GENERIC-FUNCTION (shape device))
(ADD-METHOD draw (shape device)
(AND (is-rectangle shape) (is-X-Window device))
...
)
...
Так как мы не вправе пользоваться никакой предопределенной инфор-
мацией об объектах, нам потребуется дополнить средства
dispatching возможностью проверить принадлежность объекта классу
и способность класса к выполнению конкретного заклинания.
Распределенные объекты.
Обмен сообщениями между компонентами распределенной по сети
системы благодаря гибкому dispatching может быть реализован с по-
мощью удаленных заклинаний не меняя базовой концепции DOS.
Модель клиент-сервер.
Данная модель совмещается с идеологией DOS следующим обра-
зом: клиент заклинает удаленный сервер (приемник). Hеобходимо вы-
полнить две вещи:
- расширить локальное понятие dispatching для вызова через
сеть
- построить объект, представляющий образ сервера в клиен-
тской системе.
Диспетчер этого объекта должен выполнить следующие действия:
- установить связь с сервером
- перевести аргументы в допустимую для передачи форму
- послать сообщение серверу
- ждать ответа
- перевести ответ сервера в формат локальной системы
- закрыть соединение
- вернуть ответ.
Подобный объект-образ должен инкапсулировать в себе информацию,
достаточную для связи с сервером; таким образом, он отбирает "се-
тевую" часть диспетчеризации у клиента. Hапример, в TCP/IP этот
объект описывается как
TYPE NetObj = Obj.T OBJECT
hostname : TEXT ;
portnum : CARDINAL ;
OVERRIDES
dispatcher := NetObjDispatcher ;
END
Подобным методом реализуются и другие сетевые модели. Отдельно
следует заметить, что при большом количестве объектов зачастую
целесообразно присвоить им уникальные идентификаторы или индексы,
хранящиеся отдельно от них самих.
Dispatching объектов в БД.
В объектно-ориентированных БД структура программы опреде-
ляется сущностью и отношениями неких постоянных объектов. Различ-
ные базы предлагают свои специфические модели в зависимости от
целей вычислений. Проблема dispatching этих объектов схожа с
проблемой реализации распределенных систем; для поддержания их
общности мы должны:
- вынести ссылки на объекты за пределы БД;
- реализовать заклинание над объектами с использованием
идей dispatching классов и родовых функций.
Для доступа к объектам скорее всего потребуется применять методи-
ку, описанную для распределенных систем. Важное отличие заклю-
чается в том, что для заклинания объектов БД сервер БД и его об-
раз должны поддерживать сообщение "заклинание". В конкретно изго-
товленной реализации для этого применялось такое средство объек-
тно-ориентированных БД как динамическое заклинание. Действия сер-
вера БД при получении заклинания:
- оттранслировать аргументы в рабочий формат;
- составить из аргументов список и вызвать механизм динами-
ческого заклинания для его обработки;
- вернуть результат как список из значений базовых типов и
идентификаторов объектов.
Dispatching базы правил.
Традиционно системы работающие с базами правил имеют закрытую ар-
хитектуру и включают в себя интерфейс базы данных, хранящей эти
правила. В результате правила оказывают существенное влияние на
системные вопросы, такие как база данных и язык программирования.
В этой серии экспериментов авторы пытались понять метод обеспече-
ния гибким dispatching связи между правило- и объектно-ориентиро-
ванными парадигмами.
Модель базы правил.
Традиционно системы состоят из двух частей: правил и фактов.
Сердцем системы является процессор правил, использующий правила и
факты для достижения цели. Единственным путем внесения в систему
данных является декларация фактов. Правда, системы работающие с
большими объемами данных, часто объединены с БД и пользователь
может как декларировать факты, так и напрямую работать с таблица-
ми БД.
Для приведения баз правил к виду объектов мы должны реализо-
вать общий механизм, позволяющий им доступ к внешним данным - се-
тевые заклинания; в частности, это даст БП доступ к удаленным БД.
Теперь БП сама может рассматриваться как распределенный объект.
Правила как методы объекта.
Для использования правил в работе объекта следует просто
реализовать диспетчер, делегирующий работу процессору правил в
соответствии с заклинанием. Вкупе с доступом к БД мы получаем,
что база правил есть объект с состоянием - данными БД и методами -
правилами, также хранящимися в БД. Обычно нежелательно, чтобы
правила напрямую обращались к БД; соответственно, диспетчер дол-
жен передавать базе правил свой собственный идентификатор и про-
цессор правил будет обращаться к нему с заклинаниями доступа к
данным.
Вынесенные заключения и нерешенные проблемы.
В ходе экспериментов выяснилось следующее:
- хотя в начальной идее заклинание разбивалось на адреса и
аргументы, часто удобно рассматривать заклинание как неразрывную
сущность;
- "хорошие" сообщения по идее должны пониматься всеми под-
держиваемыми объектами. Hепонятно, как быть в случае, когда сооб-
щение бессмысленно для принимающего - ответить некоторым стандар-
тно-бессмысленным образом или отдать объекту и позволить ему об-
работать и/или сгенерировать исключение;
- возникают вопросы с конкурентным доступом к объектам в
распределенных системах. В настоящее время идет разработка допол-
нений, которые позволят реализовать любой из методов управления
конкуренцией, предлагаемый в прикладных системах;
- метаобъекты. В системе следует организовать некий мета-у-
ровень и разрешить доступ к нему диспетчеров. Явное указание ал-
горитмов диспетчеризации подобно использованию goto: и гибко, и
опасно. Постепенно выделятся общие пути диспетчеризации, которые
станут высокоуровневыми абстракциями;
- отделение мета- и базового уровня. Смесь в одном диспетче-
ре доступа к обоим уровням трудна для восприятия;
- оптимизация. Преимуществом предложенной схемы является то,
что она не рассчитана на конкретный метод диспетчеризации и, сле-
довательно, возможно оптимизировать какие-либо части работающей
системы не нарушая работы остальных.