Объектные модели
Итак, в моделях CORBA и COM клиент получает обслуживание от сервера объекта, запрашивая метод, заданный в интерфейсе объекта. Важной характеристикой обеих технологий является четкое разграничение интерфейсов, которые - суть абстрактный набор связанных методов, и конкретных реализаций этих методов. Клиенту доступно описание интерфейса объекта, через которое он получает доступ к методам, то есть функциональности данного объекта. Детали реализации методов от клиента полностью изолированы. Метод вызывается по ссылке, и реальные действия выполняются в адресном пространстве объекта.
Однако за этим фундаментальным сходством начинаются значительные различия между конкретным воплощением в двух моделях понятий объектов, интерфейсов, вызова по ссылке и т.д. На них и остановимся.
В CORBA интерфейс объекта задается с помощью определенного OMG языка описания интерфейсов (Interface Definition Language, IDL). Тип объекта - это тип его интерфейса. Интерфейс идентифицируется именем, представленным цепочкой символов. В модели CORBA определен базовый тип для всех объектов - CORBA::Object. Объект поддерживает тип своего непосредственного интерфейса и, по принципу наследования, все его базовые типы.
В СОМ объект характеризуется своим классом. Класс - это реализация некоторого множества интерфейсов. Множественное наследование интерфейсов не поддерживается, вместо этого объект может иметь несколько интерфейсов одновременно. В СОМ интерфейс может определяться путем наследования другого интерфейса. Для всех интерфейсов существует базовый интерфейс - IUknown. Для того чтобы перейти от интерфейса базового типа к унаследованному интерфейсу или от одного из интерфейсов объекта к другому, клиент должен вызывать метод QueryInterface, определенный в базовом интерфейсе IUknown. Интересно отметить, что возможность описания нескольких интерфейсов для одного объекта должна появиться теперь и в CORBA; анонсированная в сентябре прошлого года версия CORBA 3.0 в числе важных нововведений содержит и концепцию Multiple Interface [3].
Для идентификации классов и интерфейсов СОМ используются те же универсальные уникальные идентификаторы (UUID), которые приняты для идентификации интерфейсов в спецификации DCE RPC.
Можно применять и символьные обозначения интерфейса, но затем они должны быть транслированы в надлежащий идентификатор UUID. Объект в СОМ - это экземпляр класса. Клиент получает доступ к объекту с помощью указателя на один из его интерфейсов (interface pointer). Связь между классом и множеством поддерживаемых им интерфейсов достаточно произвольна. Не существует заранее заданного отношения между идентификатором класса и конкретным набором интерфейсов, и разные экземпляры класса могут поддерживать разные подмножества интерфейсов. Идентификатор класса ссылается на конкретную реализацию, и фактический набор интерфейсов для данной реализации становится окончательно известен только на стадии выполнения. Все эти особенности вытекают из существа модели СОМ, которая реализует интеграцию объектов на уровне двоичных кодов. Двоичное представление интерфейса объекта в СОМ идентично виртуальной таблице функций языка Си++. Клиент имеет доступ к интерфейсу посредством указателя на такую таблицу, а все детали реализации скрыты от него. Поэтому можно прозрачно для пользователя вносить изменения в реализацию объекта, если при этом не меняется интерфейс. Заимствованная из Си++ модель интеграции на двоичном уровне с помощью таблиц функций имеет как свои плюсы, так и минусы. Невидимая пользователю возможность замены реализаций объектов и высокая эффективность вызовов методов в пределах одного адресного пространства по аналогии с вызовом виртуальной функции в С++ - очевидные положительные стороны такой модели. С другой стороны, интеграция на уровне двоичных кодов возможна только на одной аппаратно-операционной платформе. Невозможность множественного наследования интерфейсов в СОМ - следствие использования таблиц функций. Интерфейс представляется указателем на одну таблицу, а множественное наследование повлекло бы за собой связь конкретного интерфейса с несколькими таблицами, то есть понадобилось бы несколько указателей для одного интерфейса. В СОМ принята более громоздкая, по сравнению с CORBA, структура логических связей объекта и его интерфейсов. Конечно, определение интерфейсов с помощью двоичных таблиц не зависит от конкретного языка программирования.
Но поддержка различных языков должна опираться на механизм вызовов виртуальных функций, который непосредственно применим только к Си++, а для всех остальных языков будет подвергаться определенной предварительной обработке. Поэтому по числу поддерживаемых языков СОМ уступает CORBA, в которой предусмотрен гибкий механизм отображения описаний интерфейсов в терминах IDL в соответствующие структуры того или иного языка программирования. Различие между языками IDL по версии OMG и Microsoft - одно из наиболее значительных для двух объектных моделей. В CORBA язык описания интерфейсов - важнейшая часть архитектуры, основа схемы интеграции объектов. Все интерфейсы и типы данных определяются на IDL. Различные языки программирования поддерживаются благодаря заданным отображениям между описаниям типов данных на IDL в соответствующие определения на конкретном языке. CORBA IDL задает определения, которые могут отображаться в множество различных языков, не требуя при этом никаких изменений от целевого языка. Эти отображения реализуются компилятором IDL, который генерирует исходные коды на нужном языке. В настоящий момент поддерживается отображение в Си, Си++, SmallTalk, Ada95, Visual Basic, Кобол Cobol и Java. Сам IDL синтаксически напоминает декларации типов в Си++, но отнюдь не идентичен этому языку. Если в модели интеграции объектов CORBA язык IDL играет фундаментальную роль, то Microsoft IDL (MIDL) - лишь один из возможных способов определения интерфейсов объекта. В спецификации СОМ подчеркивается, что эта модель реализует интеграцию на двоичном уровне, поэтому все спецификации и стандарты, относящиеся к уровню исходных текстов компонентов, к которым следует причислить и MIDL, рассматриваются как вспомогательные и не могут оказывать решающего влияния на общую архитектуру системы. MIDL - не более чем полезный инструментарий для написания интерфейсов. В отличие от CORBA IDL, MIDL, являющийся расширением DCE RPC IDL, не определяет общего набора типов данных, доступных различным языкам программирования.
На MIDL можно определить интерфейсы и типы данных, которые поймут программы на Си и Си++, но для Visual Basic и Java этого уже сделать нельзя. Проблему частично обещает решить новая спецификация СОМ+, которая предоставит возможности встраивания средств определения СОМ-интерфейсов в инструментарий для языков типа Visual Basic и Visual C++. Обе объектные модели предусматривают ситуацию, когда у клиента уже в процессе выполнения программы возникает потребность использовать те или иные объекты. В этом случае у клиента не будет скомпилированных команд для вызова методов, поскольку интерфейс объекта не был известен на этапе компиляции. Поэтому ему потребуются специальные интерфейсы динамического вызова. В CORBA механизм DII (Dynamic Invocation Interface) опирается на Interface Repositоry, который содержит написанные на IDL определения типов данных и интерфейсов. Конкретная реализация такого репозитария зависит от разработчика брокера объектных запросов ORB. Помимо динамических вызовов, репозитарий интерфейсов в CORBA может использоваться для систематической организации и хранения данных определенного проекта. В СОМ те же функции выполняют интерфейс Dispatch и библиотеки типов Type Libraries. CORBA и СОМ абсолютно по-разному подходят к проблемам идентификации (identity) объектов и их сохранения в долговременной памяти (persistance). CORBA вводит понятие объектной ссылки (object reference), которая уникальным образом идентифицирует объект в сети. Тем самым экземпляру объекта дается право на существование в течение некоторого времени. Объекты могут активироваться, сохраняться в долговременную память, позже вновь реактивироваться и деактивироваться, и при этом объектная ссылка будет указывать все время на одно и то же конкретное воплощение объекта. Для особо значимых объектов, предназначенных для длительного использования, объектные ссылки могут интегрироваться со службой каталогов или службой имен. Механизм долговременного хранения, то есть сохранения состояния объекта в долговременной памяти для дальнейшей его реактивации, в CORBA абсолютно прозрачен для клиента.
Клиент не имеет никаких легальных средств обнаружить: куда и каким образом сохраняется экземпляр объекта. Такой подход соответствует концепции сокрытия деталей реализации объекта от клиента. В СОМ понятие объектной ссылки отсутствует. Ближайший аналог - это механизм moniker ("кличка"), обеспечивающий преобразование символьного имени объекта в указатель интерфейса. Этот механизм действует для тех объектов, которые сохраняются в долговременной памяти. Два же активных объекта считаются идентичными, если для них совпадают указатели на интерфейс IUknown. Для долговременного хранения в СОМ поддерживаются две модели. Первая и изначальная модель предоставляет клиенту возможность управлять хранением объекта. В интерфейсе объекта, предназначенного для долговременного хранения, поддерживаются возможные типы носителей. Если необходимо восстановить объект из долговременной памяти, клиент явным образом указывает, где был сохранен экземпляр объекта и запрашивает его активацию. Однако, такая модель эффективна, скорее всего, только в настольной среде или в небольшой локальной сети, где управление хранением документов, к примеру, может быть доверено пользователю файловой системы. Другой, более поздний вариант сохранения в долговременную память в СОМ предусматривает использование Microsoft Transaction Server (MTS), который обеспечивает управление хранением со стороны сервера.