0,0
рейтинг
22 ноября 2012 в 21:18

Разработка → IBM SOM: внешняя объектная система с поддержкой наследования из песочницы

image Хотел бы поделиться своей находкой: IBM SOM. Согласно Википедии, жил да был некогда Microsoft с COM, и был IBM с SOM. В Windows и OS/2, соответственно. И были для них средства межсетевого взаимодействия: DCOM и — как вы думаете? — правильно, DSOM. Такая вот идиллия, что может сложиться впечатление, что это близнецы. Только вот в SOM было наследование, а в COM — нет, и в журналистских статейках, на которые ведут ссылки из Википедии, только об этом и речь.


Но это лишь начало путешествия в кроличью нору.

На SOM есть документация, есть обзоры, однако такими документами, по которым можно составить впечатление, я бы назвал 4 статьи под авторством Scott H. Danforth и Ira R. Forman (Айра — мужское еврейское имя):

www.edm2.com/index.php/Scott_H._Danforth

  • Release-to-Release Binary Compatibility in SOM Article by Ira R. Forman, Michael H. Conner, Scott H. Danforth and Larry K. Raper (IBM's System Object Model) (1995)
  • Reflections on Metaclass Programming in SOM by Ira R. Forman, Scott H. Danforth (1994)
  • Inheritance of Metaclass Constraints in SOM by Ira R. Forman, Scott H. Danforth (1994)
  • Composition of Before/After Metaclasses in SOM by Ira R. Forman, Scott H. Danforth, Hari Madduri (1994)


Самые вкусные моменты:

RRBC:
The goal of this engineering discipline for compiled libraries can be stated as:
Only application alteration necessitates recompilation
This implies that if the evolution of the class library does not require changes to the application source, then the application should not require recompilation.


Чуть далее по тексту разбираются возможности, которые даёт обычный, процедурный компоновщик, которые везде есть и дальше которого до сих пор не зашло, а именно, перечисляются допустимые трансформации.

Затем невзначай этот список продолжается другим списком трансформаций, для тех самых классов с наследованием. Приватная переменная объекта может быть добавлена, иерархия классов может измениться. Всё, что не требует изменения исходных кодов, не должно требовать перекомпиляции. Вот такой работой были заняты в IBM Object Technology Group (Austin).

И наконец, в RRBC приведена таблица, в которой SOM сравнивается с альтернативами (Delta/C++, OBI — мне не знакомо, но интересно было узнать). В этой таблице я, правда,
не согласен с примечанием h
Если рассмотреть Objective-C runtime отдельно от Objective-C и считать, что мы реализуем потомков только через привязки, которые не знают точные размеры экземпляров предков, узнают это значение динамически и пересчитывают все смещения, то это одно дело. Но проблема в Objective-C, который с этой точки зрения худший потребитель Objective-C runtime, потому что механизмы наследования предполагают заморозку смещений внутри предков с момента публикации API.


Приятно радует, что авторы знакомы с CLOS и не только! В таблице по одному пункту (migrate metaclass constraint downward) CLOS уступает SOM. Более подробно эта проблема (metaclass incompatibility) рассмотрена в, например, Reflections on Metaclass Programming in SOM. Суть в том, что ожидается, что метакласс потомка будет потомком метакласса родителя, иначе metaclass incompatibility. При явных метаклассах это становится возможным. Учитывая изменчивость иерархии классов и, не забывая девиз SOM, становится ясно, что то, что сойдёт с рук CLOS, не сойдёт с рук SOM.

В SOM 2.0 применено оригинальное решение проблемы: метакласс, указанный в IDL класса, теперь является не точным указанием метакласса для этого класса, а лишь ограничением. Метакласс класса должен быть потомком метаклассов каждого из родителей, а также потомком метакласса, указанного в объявлении класса. Если один из этих метаклассов удовлетворяет всем требованиям, он и берётся. В противном случае SOM runtime принимает решение скрестить все требуемые метаклассы с целью получения минимально удовлетворяющего требованиям метакласса.

Заодно в этом документе разъясняется, что такое эти метаклассы. Перескажу на примере Delphi и Java, в которых метаклассы неявные.

Итак, есть и в Delphi, и в Java помимо методов объекта ещё и методы класса. В Delphi также есть виртуальные конструкторы. Что касается Delphi, есть некий TClass, объявленный как class of TObject. Каждый раз, как в классе Delphi добавляется метод класса или виртуальный конструктор, в SOM это было бы аналогично наследованию метакласса с добавлением в него этих методов. В Delphi и Java метаклассы неявные, и цепочка их наследования почти зеркалирует цепочку наследования классов. Если новых методов класса не добавилось, можно считать, что в этом случае метакласс родителя взят без изменений. TClass и другие class of… в Delphi ведут себя не так, как обычные объекты. У TObject есть, например, TObject.Dispatch, но у переменных типа TClass такой метод ну никак не вызвать. И любой другой метод объекта TObject не вызвать у переменных типа TClass. TClass не наследник TObject, они в других отношениях. В Java немного иначе: есть java.lang.Class и он действительно наследник java.lang.Object со всеми вытекающими. Однако, если у класса есть метод, и нам попал в руки экземпляр java.lang.Class, представляющий потомка этого класса, то вызвать какой–то метод у такого экземпляра не получится. У класса–как–объекта нет тех же методов, которые есть у класса–просто.

Теперь, после того, как я написал, как обстоят дела в Delphi и Java, должно быть понятно, что такое метаклассы: в SOM классы–объекты — это полноценные объекты, и их методы — это полноценные методы объекта, такие же полноценные, как и у их экземпляров. А так как у объектов методы не могут существовать просто так, они должны быть объявлены в классе этого
объекта. Класс класса — это и есть метакласс. Сам метакласс обычно в качестве своего класса имеет SOMClass, но и он, будучи полноценным объектом, может иметь какой–то другой класс. Вынуждая тем самым SOM runtime скрещивать метаметаклассы при необходимости на то.

In effect, inheritance is given a new dimension


Вот такой вот близнец COM с поддержкой наследования.

Я писал обзор объектных систем, и SOM сияет в свете своих возможностей.

А теперь две новости:

Хорошая: SOM был портирован в том числе и на Windows NT. Другими таргетами проблематично воспользоваться. AIX для PowerPC, OS/2 не каждому эмулятору PC по зубам и денег стоит, Himalaya NonStop — и думать нечего, Mac OS Classic — тоже как–то далековато.

Версия SOM 3.0 была доступна бесплатно в виде февральской беты 1996 года и декабрьского релиза, из которого некоторые возможности, которые не смогли довести до ума, вырезали. Например, Direct-To-SOM позволял не .h делать из .idl, а, наоборот, .idl из .h. Пишем на модифицированном компиляторе C++, получившийся код использует SOM и благодаря этому становится гибким. В отличие от Delta/C++, возможными потребителями библиотек автоматически становятся другие компиляторы C++ и компиляторы других языков программирования.

Плохая: я нигде не могу найти SOMobjects 3.0 Developer's Toolkit for WinNT. Что–то случилось в 1997м или 1998м году такое страшное, что ладно бы IBM прекратила разработки в этом направлении, так нет же, надо было отовсюду вычистить SOM из своих закоулков. На FTP я только документацию нашёл, а самих файлов нет. Только благодаря архиву Hobbes сохранилась версия для OS/2, остального — тю–тю. Ставил VisualAge C++ 4.0, думал, в комплекте идёт. Нет, не идёт.

Я несколько месяцев назад начал с людьми связываться, и которые в разработке участвовали, и которые сами использовали, в том числе и версию для Windows. Приятно, что отвечают, можно ещё найти кого–то, но у них нет этих файлов. Особенно меня убивает, когда
так отвечают те, кто, я знаю, вложил много энергии и творческих сил в эту работу
Hi, Ivan,

I'm sorry to say that although I was the chief programmer for release 1 and 2 of SOM (I even signed the disks that were to be used as the general availability media and sent to production) I had left the company by the time 3.0 came out and had no contact with the team at that point.

I don't know anyone who has the binaries at this time. It is a shame that IBM marketed SOM so poorly — for a while there we thought we were going to change the world.

Sorry I can't help you.

andy


Идеи, у кого ещё мог файлик остаться, временно исчерпаны. Насколько я могу судить, на физическом носителе SOM 3.0 не распространялся по отдельности. На CD-ROM должны быть версии и для OS/2, и для WinNT, и для AIX. Судя по имени файла som30os2.zip (всё, что сохранилось в Интернет), это версия именно с CD-ROM. Internet-sized файлы имели другие имена: som30ox1.zip, som30ox2.zip and som30ox3.zip.

Что дальше?


Во–первых, при некотором интересе к SOM могут–таки найтись недостающие файлики. По моему мнению, до сих пор актуальные, даже учитывая потребность в версиях для Linux и Mac OS X. Мне нравится идея исполняемых файлов в формате PE COFF, умеющих обнаружить исполнение внутри wine, загрузить родные для OS версии wxWidgets или Qt и, используя их, забыть свои корни. Даже не имея исходных кодов SOM, можно иметь пользу, а наличие работающего SOM и работающего кода, использующего SOM, поможет создать совместимую замену. Линуксовый wxWidgets так запросто не получится использовать из программы, компилирующейся в Windows. Тут–то и пригодилась бы прослойка, и почему бы не SOM?

Во–вторых, сама по себе осведомлённость о SOM — это матрица в сознании, влияющая на принятие решений разработчиками. У тех, кто разрабатывал GObject, такой матрицы в сознании не было, и GObject в SOM так и не вырос.

UPD. Файлик нашёлся: som30nt.zip!

Человек, который дал этот файлик, сам находится в поисках SOM 3.0 под AIX, и, кроме того, разрабатывал открытую замену SOM: somFree. tardist для IRIX я распаковать не смог, попросил выложить на open source хостинг.

Если будете ставить VisualAge C++ 4.0 for Win32, учтите, что он может на современных Windows выносить нафиг PATH. Переменные среды надо бекапить.

UPD2. somFree на SourceForge. Пока только для POSIX систем.

Тем временем мне удалось разобраться с IBM SOM на VAC++ 4.0 и даже удалось собрать и запустить animals с использованием Borland C++ 5.5 Free.

В краткосрочной перспективе я хотел бы выложить объединённый дистрибутив IBM SOM & Borland C++ 5.5 Free, в котором из коробки можно было бы собрать и посмотреть все примеры и получить ответы на свои вопросы самолично, а не из журналистких пропагандистских статеек. Исполняемые файлы говорят громче слов.
Иван Левашев @OCTAGRAM
карма
22,0
рейтинг 0,0
Фрилансер
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (11)

  • +2
    В COM есть наследование
    • 0
      Меня тоже смутил этот факт, так как я успешно наследовался от коклассов. Хотелось бы, чтобы автор прояснил этот момент.
      • 0
        Были ли эти коклассы написаны на одном языке, собраны одним компилятором и собирался ли потомок с использованием исходного кода предка?
        • 0
          Не знаю, как это делал Xitsa, но в COM имеется языконезависимый механизм.
          Называется этот механизм «агрегация» или «агрегирование» (aggregation)
          • 0
            Да, но это не то же самое. Нельзя взять какой–нибудь базовый кокласс, как–нибудь без проблем агрегировать его, добавить своих функций и использовать как аргумент метода, ожидающий предка (а не интерфейс предка). На одних интерфейсах всего не сделаешь, часто нужно, чтобы полученный объект имел не только фиксированный интерфейс, но и особенность реализации внутри себя. Ну, скажем, нельзя реализовать какой–нибудь не предназначенный для этого интерфейс Office и передать этот фальшивый объект настоящему объекту Office как аргумент. Или, если написать COM–версию ASIO, то рано или поздно дело дойдёт до select(), и потребуются OS–специфичная информация.

            При наследовании предок управляет тем, какие интерфейсы будут у потомка, и набор этих интерфейсов может измениться без участия потомка. При агрегации только контейнер единолично решает, какой набор интерфейсов он поддерживает, реализуя сам или делегируя одному из агрегированных объектов. Даже, если переписать эту логику на обратную: все интерфейсы, которые мы не знаем, направлять на делегацию внутреннему объекту, среди этих неизвестных интерфейсов может оказаться следующая версия интерфейса объекта, и в этом случае нужно что–то сделать, чтобы старые методы этого неизвестного интерфейса обрабатывались контейнером. Это можно сделать при помощи кооперации со стороны внутреннего объекта. Наверное, ничего неразрешимого, но дело в том, что это не является продуманным вариантом использования COM, и, если работать в этом направлении, то будет написан новый код, который частью COM не будет, и, учитывая все уровни косвенности, результат будет хуже, чем если с самого начала делать объектную систему, поддерживающую весь набор трансформаций.
            • 0
              Вы путаете две ситуации:

              1. Берем базовый класс (A), расширяем его (Б) и передаем третьему компоненту (В), ожидающему А.
              2. Берем базовый класс (А), расширяем его (Б) и возвращаем его той же самой библиотеке, в которой находится А.

              Так вот, первая ситуация в COM решается без особых проблем. Вторая же зачастую вообще невозможна в статически типизированных языках (попробуйте в Java от SelectableChannel унаследоваться, чтобы его потом Selector распознал).

              Что же по поводу внезапно появившегося нового интерфейса в базовом классе — все современные языки подвержены той же самой проблеме, но только с внезапно появившимися методами.
              • 0
                Как можно расширить базовый класс средствами только COM?

                У нас есть возможность получить из чужой библиотеки готовый экземпляр кокласса или же фабрику, которая сделает экземпляр. Переделать уже созданный экземпляр в его как бы потомка без агрегации не представляется возможным.
        • 0
          кокласс был написан на С++, наследник на .Net.
          По сути это вариант агрегации.
          потребовалась кооперация от кокласса, чтобы при переопределении методов кокласс мог их вызывать.
          • +1
            Я, наверное, уточню ситуацию:
            У нас есть свой скриптовый язык на базе .Net, на котором можно писать пользовательские обработчики событий.
            Для того, чтобы добавление новых событий не приводило к неработоспособности старых вариантов был сделан кокласс–стандартный обработчик. И пользовательский класс наследовал от кокласса стандартным для .Net'а способом.

            Для того, чтобы кокласс мог вызывать методы унаследованного класса, для this делался QueryInterface и вызывались методы у полученного интерфейса.
  • 0
    А еще есть такая штука: NOM — ремейк SOM — svn.netlabs.org/v_nom

    Вот еще про SOM на русском:
    Объектно-ориентированное программирование в eComStation, Часть 1: Введение — ru.ecomstation.ru/showarticle.php?id=144
    • 0
      Плохо, что эта вещь не является drop-in replacement. Когда вышел SOM 2.0, это не сломало приложения, использующие SOM 1.0, хотя у первого и второго были существенные отличия. NOM не продолжает эту традицию. NOM плохо документирован и существует в большей степени не сам по себе, а ради того, чтобы был сделан Voyager, кроссплатформенный аналог WPS. Из того, что я читал про WPS, помню, что SOM там используется по–особенному, не полностью, и, если, например, использовать множественное наследование, WPS падает. В связи с чем напрашивается вопрос, а не будет ли NOM таким же недо–SOM, который применяется в WPS?

      Сильно смущает обязательная сборка мусора в NOM

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