ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД И СЕТЕВОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ

, , Журнал «ПРОГРАММИРОВАНИЕ» №6,1990

1.ВВЕДЕНИЕ

Использование объектно-ориентированнного подхода, как нам кажется, дает существенные результаты практически во всех областях программирования. Не является исключением и сетевое программное обеспечение. В ИПМ АН СССР накоплен до­вольно большой опыт создания и использования сетей ЭВМ с объектно-ориентированной архитектурой. В период с 1976 г. по 1981 г. были сделаны пробные реализации и построена объектно - ориентированная сетевая архитектура, которая и используется по настоящее время[1,2]. В 1983 г. была введена в эксплуата­цию сеть СЕКОП из ЭВМ БЭСМ-6, реализованная в соответствии с этой архитектурой. В 1988 г. была готова первая реализация сети с объектно-ориентированной архитектурой для IBM PC, ДВК и ЕС ЭВМ. Эта сеть получила название РУСЛАН и в настоящее время продолжает развиваться. Исходя из нашего опыта, по-ви­димому, можно сделать два основных вывода:

- производительность программиста при создании распреде­ленных программных систем в сети с объектно-ориентированной архитектурой принципиально выше по сравнению с работой в сети с традиционной архитектурой. Здесь под традиционной се­тевой архитектурой понимается представление распределенной программной системы в виде совокупности распределенных по различным ЭВМ процессов. Причем эти процессы взаимодействуют друг с другом, обмениваясь сообщениями с помощью примитивов "послать - принять". Создавая распределенную систему, прог­раммист вынужден строить частные протоколы связи между свои­ми процессами, что является нетривиальной задачей по крайней мере для программиста, привыкшего к традиционному локальному программированию. В сети с объектно-ориентированной архитек­турой распределенная программная система строится в виде со­вокупности объектов-исполнителей операций, распределенных по различным ЭВМ. Эти объекты взаимодействуют путем вызова опе­раций друг в друге. В этом случае локальный и удаленный вы­зовы операций синтаксически неразличимы в тексте программы. Сеть, как средство, связи превращается просто в один частный случай механизма связи между вызывающей и вызываемой прог­раммами. Как следствие сложность локального и распределенно­го программирования при прочих равных условиях становится практически одинаковой;

НЕ нашли? Не то? Что вы ищете?

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

Принципы построения сети с объектно-ориентированной ар­хитектурой, разработанной в ИПМ АН СССР, интерфейсы для пользователей, сетевой протокол удаленного вызова операций описаны достаточно подробно в ранее опубликованных работах [1,2,3,4,5]. В данной статье нам хотелось бы остановиться в основном на другой стороне проблемы - обратном влиянии сете­вой архитектуры на объектно-ориентированные средства. Дело в том, что распространение некоторого метода за пределы облас­ти, в которой он первоначально возник, часто приводит к по­лезному обобщению этого метода, очищению его от частных ре­шений, которые естественным, однако логически не обязательным, образом были привнесены в него из исходной об­ласти применения. Как нам кажется, в объектно-ориентирован­ном подходе именно так обстоит дело с динамическим связыва­нием, ссылками на объекты, а также со способом создания, хранения и адресации объектов. В сетевой обстановке перечис­ленные проблемы по необходимости должны решаться способом, отличным от тех, которые используются в известных нам ло­кальных реализациях (см., например, [6]).

До рассмотрения именно различий локального и распреде­ленного случаев нам необходимо хотя бы кратко описать расп­ределенный случай объектно-ориентированного подхода. Некоторое количество локальных реализаций объектно-ориенти­рованного подхода считается известными.

2.ОБЪЕКТНО-ОРИЕНТИРОВАННАЯ СЕТЕВАЯ АРХИТЕКТУРА

Начнем с перечисления проблем, которые должны быть реше­ны в рамках любой архитектуры для распределенной обработки:

- адресация в пределах сети компонент распределенной

системы (программ и данных);

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

- преобразование представления данных для разных ЭВМ,

ОС и языков;

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

- параллелизм выполнения, который является реальным в отличие от имитируемого в случае одной ЭВМ.

Рассмотрим объектно-ориентированную сетевую архитектуру, использованную при разработке сети РУСЛАН. Прикладной уро­вень строится в виде множества объектов-исполнителей опера­ций, которые взаимодействуют путем вызова операций друг в друге. Удаленный вызов операций поддерживается с помощью единственного протокола УДВ. Этот протокол в данной архитек­туре заменяет собой протоколы общего назначения на приклад­ном уровне модели ISO/OSI [7], а также протоколы 6, 5 и 4 уровней этой модели. Протоколы нижележащих уровней можно считать неспецифичными для моделей. Потенциально бесконечное множество прикладных протоколов для частных применений моде­ли ISO/OSI заменяются просто конкретными прикладными подсис­темами (объектами-исполнителями), взаимодействие которых, вообще говоря, не несет никакой сетевой специфики. Для прог­раммирования распределенных сетевых систем естественно ис­пользовать широко распространенные языки, например такие, как Си и Фортран, расширив их соответствующими средствами. При объектно-ориентированном расширении языков для распреде­ленной обработки были использованы следующие понятия:

- переменная типа объект-исполнитель операций. Под ти­пом здесь понимается набор имен операций, которые может вы­полнять объект, указываемый данной переменной. Значением та­кой переменной является ссылка на объект-исполнитель, который расположен возможно в удаленной ЭВМ. В данном изло­жении нам удобно называть переменными также и формальные па­раметры процедур (подпрограмм);

- кластер, являющийся реализацией типа объекта-исполни­теля. Кластер представляет собой набор подпрограмм, реализу­ющий операции данного типа. Для этого набора подпрограмм в заголовке кластера определяются общие переменные, называемые представлением объекта;

- экземпляр объекта-исполнителя или просто объект-ис­полнитель. Создается из кластера и индивидуального набора значений переменных представления;

- файл объектов - это специальный объект, умеющий вы­полнять операцию "создать объект" с указанным кластером, а также операции "уничтожить", "найти". Значением переменной, заданной в качестве параметра-результата операции создания исполнителя, становится ссылка на созданный объект. Естест­венно, что с одним кластером может быть создано много объек­тов. Существенно, что одной переменной могут быть в разные моменты присвоены ссылки на исполнители с разными кластера­ми, но, естественно, с соответствующими наборами операций (в объектно-ориентированных языках такое свойство называется полиморфизмом). Единственное условие - набор имен операций, определяющий тип переменной, должен быть подмножеством набо­ра имен операций, реализуемых кластером созданного объекта. Файлы объектов могут располагаться как в оперативной памяти, так и на дисках. Введение файлов объектов - это принципиаль­ный шаг, позволяющий в единой системе программирования ес­тественным образом объединить как традиционные языковые средства, так и некоторые возможности баз данных;

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

В целом предлагаемая схема функционирования прикладного уровня такова:

- имеется множество объектов-исполнителей операций, ко­торые хранятся в файлах объектов. Файлы объектов возможно рассредоточены по различным ЭВМ сети;

- имеется множество процессов, выполняющих подпрограммы в кластерах объектов. В момент вызова операции в другом объ­екте, возможно удаленном, процесс "перетекает" в этот другой объект;

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

В данной модели объекты и процессы находятся в соотно­шении "много - много". А именно, один процесс может прохо­дить через много объектов, расположенных в разных ЭВМ. Конк­ретно это означает наличие распределенного по этим ЭВМ стека для вложенных вызовов подпрограмм из кластеров объектов. С другой стороны, несколько процессов могут одновременно войти в один объект. При необходимости они могут синхронизоваться на общих переменных представления этого объекта. Для этого достаточен любой известный в локальном случае набор средств.

Отметим, что в модели ISO/OSI принято соотношение "один

- один". А именно, процесс фактически отождествляется с под­системой (объектом).

Перечислим, как решаются приведенные выше сетевые проб­лемы, когда распределенная система представляет собой мно­жество исполнителей, взаимодействующих путем вызова опера­ций:

- адресация. Значением переменной типа исполнитель яв­ляется ссылка, указывающая на объект-исполнитель, располо­женный в любой ЭВМ сети. В ссылке хранится уникальный в пре­делах всей сети идентификатор объекта (УИД), перечень указателей на операции, которые может выполнять данный объ­ект, и указатель на сетевую процедуру связи. УИД может быть дополнен различного рода физическими адресами, оптимизирую­щими доступ. Тогда вызов удаленной операции через рассматри­ваемую ссылку и процедуру связи попадает в сетевое обеспече­ние, которое транспортирует его до вызываемого объекта-исполнителя и возвращает назад результаты выполнения операции;

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

- преобразование представления. В механизм расширения языка программирования объектно-ориентированными средствами входит генерирование по описаниям переменных дескрипторов, описывающих их тип (целый, вещественный, массив, запись, ис­полнитель и т. д.). Тогда сетевое обеспечение, имея в момент траспортировки вызова тип данных, тип языка и тип ЭВМ, легко преобразует представление;

- нейтрализация сбоев. Хранение объектов в файлах объ­ектов (стабильная память), уникальные идентификаторы объек­тов позволяют естественным образом использовать известную в базах данных технику неделимых цепочек операций, контрольных точек и рестартов. Оказалось очень полезной в распределенном случае обработка исключительных ситуаций, аналогичная ло­кальной обработке. Исключительная ситуация распространяется по цепочке вложенных вызовов "вверх" до обработчика через все ЭВМ, по которым прошел процесс выполнения этих вложенных вызовов;

- параллелизм. В приводимой схеме среда связи между ЭВМ оказывается прозрачной для вызовов операций. Сетевое обеспе­чение с логической точки зрения является лишь некоторой час­тной реализацией общего механизма вызова операций. Все со­держательные действия выполняются внутри исполнителей. Поэ­тому проблемы создания процессов и их синхронизации сводятся к локальному случаю и могут быть решены с помощью хорошо из­вестных локальных средств, например, семафоров, мониторов и т. д.

Сделаем выводы из выше сказанного:

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

- распределенный случай сводится к локальному с помощью удаленного вызова операций. Сеть становится одним из частных механизмов связи между подпрограммами. Для программиста, с точки зрения техники программирования, исчезает разница меж­ду локальным и распределенным случаями. Он может пользовать­ся в обоих случаях едиными средствами, исторически доказав­шими свою достаточность и удобство.

3. ВЛИЯНИЕ СЕТЕВОЙ ОБСТАНОВКИ НА ОБЪЕКТНО-ОРИЕНТИРОВАН­НЫЙ ПОДХОД

Рассмотрим основные особенности сетевого случая по срав­нению с локальным, а также влияние этих особенностей на объ­ектно-ориентированную архитектуру. Как нам кажется, одно из существенных отличий распределенных систем от локальных в настоящее время в том, что при раскрутке распределенных сис­тем часто главная программа запускается позже ряда подсис­тем, с которыми эта главная программа должна динамически связаться и использовать их. Конечно, и в локальном случае можно найти примеры такой ситуации. Например, операционная система запускается до любой прикладной системы, которая ис­пользует ее операции. Однако, операционная система является предопределенным объектом с предопределенным набором опера­ций, и увязка с ними выполняется чаще всего статически. Нап­ротив, в распределенном случае естественно, что в маши­нах-серверах заранее запускаются разнообразные подсистемы, к которым впоследствии динамически подключаются программы-за­казчики. Причем на разных ЭВМ, возможно, имеются функцио­нальные дубли подсистем, поставляемых различными поставщика­ми, и программа-заказчик может динамически выбрать ту или иную реализацию нужной ей функции. Реализация указанной воз­можности требует от языка программирования и его поддержки времени счета ряда средств, которые, как нам кажется, от­сутствуют в известных нам объектно-ориентированных локальных реализациях. Рассмотрим требуемые средства в порядке, соот­ветствующем естественной последовательности работы в сети ЭВМ. Требуется:

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

- возможность динамически связать программу-заказчик с найденным объектом-исполнителем. Отсюда вытекает потребность иметь в качестве значения переменной типа исполнитель доста­точно сложную ссылку на объект. В этой ссылке должен хра­ниться набор имен операций, необходимых программе-заказчику, а после связывания с конкретным объектом УИД этого объекта, указатели на процедуры, реализующие операции, и т. д. Здесь важно подчеркнуть, что тип переменной-исполнителя при напи­сании программы-заказчика услуг определяется в виде набора требуемых ей операций возможно путем рассмотрения уже имею­щихся подсистем и их наборов операций. При этом выбирается некоторое удобное для данной программы подмножество опера­ций. Именно поэтому в использованной нами архитектуре под типом объекта-исполнителя понимается просто набор имен опе­раций. Это позволяет динамически связать программу-заказчик с любой подсистемой, которая в частности реализует и подмно­жество операций с этими именами. В таких сравнительно старых языках как Ада и Модула-2 динамическое связывание просто от­сутствует. В новых объектно-ориентированных системах на ос­нове языка С++ и в TURBO PASCAL 5.5 фирмы BORLAND динамичес­кое связывание, следуя языку СИМУЛА-67, ограничено соотношением базовый тип в программе-заказчике и производный тип в подсистеме-исполнителе. При этом базовый тип должен быть явно указан в описании производного типа и тем самым должен быть определен до него. Выше было показано, что тип в программе-заказчике часто определяется позже реализации ис­пользуемого объекта. Главное в данной ситуации то, что меха­низм динамического связывания программы-заказчика с объектом - исполнителем, как нам кажется, никакого отношения к содер­жательному понятию "наследования" и "родительского" типа не имеет.

Подведем некоторые итоги. Введение понятия файла объек­тов, трактовка типа переменной-исполнителя, особенности реа­лизации ссылок на объекты явились следствием сетевой специ­фики и отсутствия соответствующих средств в известных нам локальных реализациях объектно-ориентированных систем. Как нам кажется, указанные средства не являются специфичными именно для распределенного случая и являются естественным обобщением, уместным и для локального случая. В качестве примера возможного применения этих средств в локальном слу­чае укажем на использование стабильной файловой памяти объ­ектов для организации контрольных точек и рестартов, а также для хранения общедоступных подсистем в крупных ЭВМ.

4. ПРИМЕР РАСПРЕДЕЛЕННОГО ПРОГРАММИРОВАНИЯ

Приведем пример, который написан на языке СИР2, являю­щимся объектно-ориентированным расширением языка СИ. Расс­матриваются две программы, возможно расположенные на разных ЭВМ. Программа-исполнитель на той ЭВМ, на которой она выпол­няется, создает объект-исполнитель с кластером ANYCLUST и затем регистрирует этот объект под именем ANYOBJ в некотором сетевом каталоге, известным в сети под именем PUBLICDIR. Этот каталог возможно расположен на другой ЭВМ. Програм­ма-заказчик, выполняющаяся возможно на третьей ЭВМ, находит в сети этот объект и вызывает в нем операцию ANYOPER1. При­водимые ниже программы могут быть выполнены с использованием либо трех, либо двух, либо одной ЭВМ. При этом как исходные тексты программ, так и машинный код (только в случае одно­типных ЭВМ) будут идентичными для всех трех случаев.

/* - программа-исполни*/

/* определение кластера ANYCLUST */

clust ANYOPER1, ANYOPER2 ANYCLUST

/* переменные представления объекта */

int... ; char... ; serv... ; и т. п.

;

clbody ANYCLUST

oper ANYOPER1( ... )

/* тело функции, реализующей операцию ANYOPER1 */

oper ANYOPER2( ... )

/* тело функции, реализующей операцию ANYOPER2 */

/* Головная функция */

main()

/* описание четырех переменных типа объект-исполнитель, указыва­ющих на:

- файл объектов текущей задачи - переменная TFO

- предопределенный каталог текущей ЭВМ - переменная DIROWN

- общесетевой каталог, зарегистрированный в текущей ЭВМ под именем PUBLICDIR, - переменная DIR

- вновь создаваемый объект - переменная OBJ

*/

serv CREATE TFO;

serv FIND, ENTER DIR, DIROWN;

serv ANYOPER1, ANYOPER2 OBJ;

/* Сетевое инициирование */

ninit();

/* Получение ссылок на файл объектов задачи и каталог своей ЭВМ */

get_tfo(res TFO);

get_dir(res DIROWN);

/* Создание объекта */

TFO. CREATE(res OBJ, ANYCLUST);

/* Подключение к сетевому каталогу */

DIROWN. FIND(res DIR, "PUBLICDIR");

/* Регистрация объекта в каталоге */

DIR. ENTER(OBJ, "ANYOBJ");

/* Остаемся резидентом в ожидании вызовов операций */

nkeep();

/* - программа-заказчик ----*/

main()

serv FIND DIR, DIROWN;

serv ANYOPER1 OBJ;

/* Сетевое инициирование */

ninit();

/* Получение ссылки на каталог своей ЭВМ */

get_dir(res DIROWN);

/* Подключение к сетевому каталогу */

DIROWN. FIND(res DIR, "PUBLICDIR");

/* Поиск объекта в каталоге */

DIR. FIND(res OBJ, "ANYOBJ");

/* Вызов целевой операции */

OBJ. ANYOPER1( ... );

ЛИТЕРАТУРА

1. , и др. Вызов процедур в распределенных системах. Методические материалы и документация по пакетам прикладных программ, вып. 24, ч. 1, Москва, МЦНТИ, 1983, стр. 104-130.

2. A. I.Ilushin, A. N.Myamlin, V. S.Shtarkman, Computer Network Software Design Based on Abstract Objects, Information Processing 83, Paris, 1983, pp. 23-28.

3. , и др. Объектно-ориентированные средства для программирования распределенных систем. Методические ма­териалы и документация по пакетам прикладных программ, вып. 31, ч. 1, Москва, МЦНТИ, 1986, стр. 30-57.

4. , Илюшин программиро­вание на базе языка Си. XIV Всесоюзная школа-семинар по вы­числительным сетям. Тезисы докладов. Москва-Минск, 1989, ч.1, стр. 53-58.

5. , , Дерябин ­ные вычисления в Фортране. XIV Всесоюзная школа-семинар по выч. сетям. Тезисы докладов. Москва-Минск, 1989, ч.3, стр. 286-290.

6. Bjarne Stroustrup, The C++ Programming Language, Addison-Wesley, 1986, 328 pp.

7. ISO 7498 Information processing systems - Open Systems Interconnection - Basic Reference Model.

Телефон для справок: (Москва)