ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД И СЕТЕВОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ
, , Журнал «ПРОГРАММИРОВАНИЕ» №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.
Телефон для справок: (Москва)


