Начнем с концепции «клиент-сервер». Это словосочетание с некоторых пор стало привычным и связалось с контекстом доступа к базам данных. Точнее, «для широкой публики» оно стало означать «клиент - сервер базы данных». Хотя на самом деле - это совсем не так. Концепция «клиент-сервер» значительно мощнее, чем принято об этом думать. Идея концепции исходит из понятия «сервиса» - некоторого действия, совершить которое зачем-то требуется стороне A и которое она сама выполнять не умеет. Зато стороне B совершение этого действия не нужно, но как раз она-то и умеет его совершать. В таком случае сторона A каким-то образом вынуждает сторону B совершить это действие и предоставить стороне А результат. В таком взаимодействии сторона, которая умеет совершать действие, но не имеет никакой инициативы его совершения называется «сервером», а сторона, которая состоит только из инициативы - называется «клиентом». В этом взаимодействии «клиент» запрашивает, а «сервер» предоставляет «сервис».
Многие привычные случаи программного взаимодействия можно переосмыслить под этим углом, например внутри обычной программы «вызывающая процедура» очевидно является клиентом, а «вызываемая» - сервером. Просто о них не принято думать в таких терминах, хотя ничего некорректного в этом нет. И во взаимодействии каких либо машин, программ, объектов, когда один запрашивает у другого совершить какое-либо действие запрашивающий - всегда клиент, а исполняющий - всегда сервер.
Понятия клиента и сервера - динамические понятия. В диалоге объектов, т.е. когда они вызывают друг-друга попеременно, в разном взаимодействии каждый из них попеременно будет и клиентом и сервером - термин никоим образом не означает иной специализации, чем это требуется для самого взаимодействия.
Объект - это абстракция прямо отражающаяся в окружающей реальности. У любой сущности видимого мира есть состояние и поведение. В computer sciences состояние описывается данными, а поведение - процедурами. Объединив оба понятия в одну сущность получим объект - классика, начиная уже со времен Страуструпа! Является теоремой, но сейчас доказывать уже не нужно - любая программа может быть сконструирована как совокупность взаимодействующих объектов. Вот и посмотрим, как бы могли между собой взаимодействовать части такой единой программы. Соответствующая конфигурация показана на рис. 1.
Рис.1 Конфигурация модуля, сконструированного в ООП
Здесь имеется два взаимодействующих объекта C и S которые располагаются в одном исполняемом модуле, а модуль, в свою очередь, располагается в среде операционной системы. Расположение в одном модуле позволяет «по рождению» знать друг о друге все, что знал о них компилятор. Также, здесь и ниже под термином «взаимодействие С и S» мы имеем в виду, что C получил ссылку на S и вызывает его метод.
Разделим модуль, изображённый на рис.1 на два модуля, так чтобы в каждом оказалось по одному объекту. Этим мы разорвем их взаимодействие, но не уничтожим способность объектов взаимодействовать друг с другом - ведь сами-то объекты не изменились. Сделать это можно, если один из объектов поместить в DLL, а второй оставить в EXE. Получим конфигурацию, изображённую на рис. 2:
Рис. 2 Конфигурация разделенных модулей
Рассмотрим возможный сценарий такого взаимодействия. Сразу оговоримся - сценарий «загрузки DLL по требованию» здесь невозможен - модуль MC ничего не знает о модуле MS. Это мы их наименовали так только для нашего рассмотрения. Очевидно так же, что модуль MC - загружен в память и выполняется, а иначе как бы объект C мог проявлять свои желания?
Итак, объект C имеет твёрдое намерение взаимодействовать с объектом S, а объект S - такого желания совершенно не испытывает и ведет себя пассивно: разыщут - исполнит. Более того, вообще говоря, С и вовсе неизвестно - есть ли «в живых» этот самый объект S. Пока они оба «жили» в одном модуле этой проблемы не было вовсе - и адресное пространство было одно и ссылки на объект из «своего» модуля создавались еще компилятором. А сейчас… сейчас объект С знает только, что где-то в природе должен существовать объект S и хочет его достать.
Что должен делать объект C? Что он вообще может сделать? Разумно предположить, что первое обращение последует от C к операционной системе - «я знаю, что в твоих недрах есть объект S, прошу выдать мне ссылку на него». Система в таком случае должна как-то вести учёт своего «объектного поголовья» и иметь средства отличать одни объекты от других. Без этой способности запросы такого рода не выполнить. Адрес, как характеристика объекта, здесь неприменим - адрес памяти известен только для заведомо существующих объектов, а C даже про существование S ничего не знает. Кроме того, система должна также знать, что объект S «живет» именно в модуле MS, а этот модуль - располагается во вполне определенном каталоге файловой системы. О том, какие модули составляют процесс, система знает и так.
Система, получив такой запрос из определенного процесса, должна просмотреть свой список «имя объекта - имя модуля», отыскать по имени объекта модуль, в котором тот обитает. После этого система, видимо, должна проверить - а есть ли такой модуль в числе составляющих процесс. Если такого модуля нет, то система его должна в этот процесс загрузить…
Как «сделать объект S» система, конечно, могла бы знать. Но - сколько модулей, столько и мнений, и - все их помнить? Поэтому система не будет пытаться что-то сделать сама, а совершенно стандартным образом запросит модуль MS - «выдать ссылку на объект S». Тут появляется уже некоторая возможность волюнтаризма со стороны модуля MS - система-то просила у него только ссылку. Как получается эта ссылка - создает ли модуль новый объект S всякий раз, как его запрашивают, имеет ли он объект S один на всех и всем выдает одну и ту же ссылку - дело модуля MS, а не системы.
Модуль MS «проворачивается» - он «делает объект S» в памяти, получает его адрес и возвращает этот адрес системе - «получите, что просили». Система же, зная, от кого поступил запрос, возвращает адрес тому, кто вызывал - объекту C. Поскольку объекты C и S раньше жили в одном модуле, то, как вызывать методы объекта S объект C знает! А ссылку он получил… Взаимодействие - состоялось.
Обратим внимание вот на что - в этом, нестрого изложенном сценарии взаимодействия, точно обозначены механизмы и понятия, необходимые, чтобы объекты, заведомо всё знающие о взаимодействии друг с другом могли «друг друга повстречать». Более того, эти механизмы и нужны только лишь для того, чтобы можно было «обеспечить встречу» - как взаимодействовать объекты и сами знают. И вот эту инфраструктуру мы изучим подробнее, ведь «вызов метода по ссылке на объект» - совершенно стандартная возможность, предоставляемая любым языком программирования.
Итак:
1. Все потенциально доступные объекты должны быть уникально поименованы в системе, чтобы можно было отличать один объект от другого
2. Система должна знать, в каком исполняемом модуле «обитает» объект, так, чтобы по имени объекта можно было запустить модуль, его реализующий.
3. В системе должна быть специальная, доступная всем желающим функция «дать адрес «живого» объекта по его имени» и эта функция должна делать сравнительно много работы!
4. Исполняемые модули, реализующие объекты должны иметь особый «стандартный вход», посредством которого от операционной системы они будут получать запросы на создание объектов, ими реализуемых.
5. Объекты должны заранее знать, каким образом они взаимодействуют между собой - система не вмешивается в этот процесс.
Поскольку изложенный сценарий от реального сценария взаимодействия объектов COM отличается только в мелких деталях, рассмотрим эти этапы подробнее.
Прежде всего, отметим себе, что описанная последовательность действий возникает вследствие одного-единственного обстоятельства - мы захотели, чтобы объекты, которые находятся в физически разных, заранее неизвестно - в каких, модулях, взаимодействовали друг с другом так, как будто бы они находятся в едином модуле. В этом смысле требования к протоколу их взаимодействия - философские требования. Они не зависят ни от платформы, на которой реализуются, ни от программы, которая использует такие объекты. Иными словами - всякая программа/платформа, которая захочет поддержать взаимодействие объектов в физически разных модулях как если бы они были в модуле одном - должна будет выполнить эти действия.
0 коммент.:
Отправить комментарий