IBM's System Object Model

The System Object Model (SOM), the linchpin of IBM's approach to interoperable objects, will eventually underlie all of IBM's object-technology offerings, including OpenDoc, the Taligent frameworks, and the Workplace family of operating systems.


January 01, 1994
URL:http://drdobbs.com/architecture-and-design/ibms-system-object-model/184409410

The linchpin of IBM's object-enabling infrastructure

The object industry today is a patchwork of islands of information residing within the confines of a myriad of incompatible object systems. For example, consider binary C++ class libraries that cannot be shared among developers using different C++ compilers--let alone by Smalltalk or Cobol programmers.

To address some of the key inhibitors to the widespread acceptance of object technology, and to overcome some key impediments to object interoperability, IBM created the System Object Model (SOM). SOM is the linchpin of IBM's object-enabling infrastructure. Eventually, SOM will underlay all of IBM's object technology product offerings (including OpenDoc, the Taligent frameworks, and the Workplace family of operating systems).

What is SOM?

The SOM technology was designed specifically to overcome several major obstacles to the pervasive use of object-class libraries. The goal is to enable the development of "system objects"--which can be supplied as part of an operating system, a vendor tool, or an application--with the following attributes:

To achieve this goal, the developers of SOM designed an advanced object model and implemented the object-oriented run-time engine necessary to support this model. SOM supports all the concepts and mechanisms normally associated with object-oriented systems, including inheritance, encapsulation, and polymorphism. In addition, SOM possesses a number of advanced object mechanisms, including support for metaclasses, three types of method dispatch (with both static- and dynamic-method resolution), dynamic class creation, and user intercept of method dispatch.

SOM has been commercially available since 1991, when it first appeared in OS/2 2.0. In addition to OS/2, it is now available for AIX, Windows, and Mac System 7. Over the next two years, SOM is likely to appear on other UNIX platforms and Novell's NetWare, as well as IBM's Workplace, MVS, and OS/400 operating systems. SOM has been selected by the Component Integration Laboratories (CIL) as the underlying object model and run-time engine for the OpenDoc compound-application technology. SOM is also used by Taligent (a development company that is a joint venture of Apple, IBM, and HP) in the Taligent Application Frameworks (TalAE).

One source of confusion when comparing compound document technologies has been the relationship of the OpenDoc technology to SOM. SOM is object-enabling technology. It was never intended to provide compound-document functionality. OpenDoc, developed and distributed by CLI, is built upon the SOM object model and run time, as well as SOM's distribution framework, and provides a framework specifically designed for building components, or "parts" that can be integrated into compound documents.

Backplanes and Frameworks

SOM can be thought of as analogous to the hardware backplane in a personal computer; see Figure 1. Like the hardware backplane, SOM has slots for objects or frameworks (defined later) to be inserted, analogous to the boards that plug into the hardware backplane. The major difference between a traditional PC backplane and SOM is that the PC backplane is used primarily as a communications vehicle between the computer's CPU and peripheral devices. SOM is a peer-to-peer communications vehicle interconnecting objects and frameworks with each other, rather than to a central "master" controller.


Figure 1: SOM has slots for objects or frameworks to be inserted that are analogous to the boards that plug into the hardware backplane.

SOM comes packaged with a number of frameworks. Frameworks are interrelated sets of SOM objects designed to solve a particular problem. They are analogous to the hardware boards that plug into a PC backplane, as shown in Figure 2. Like many of the boards that populate a PC backplane, the SOM frameworks are built to be extended, modified, or completely replaced. Three of the frameworks packaged with SOM are object persistence, object replication, and object distribution.


Figure 2: SOM frameworks, analogous to PC hardware boards, are interrelated sets of SOM objects designed to solve a particular problem.

The purpose of the distribution framework (sometimes called "distributed SOM") is to seamlessly extend SOM's internal method-dispatch mechanism (the piece of SOM responsible for invoking operations on objects) so that methods can be invoked in a programmer-transparent way on objects in a different address space or in a different machine from the caller.

The object-distribution framework can be viewed as a board fitting into the SOM backplane that has some components preinstalled, as well as empty sockets for additional components; see Figure 3. Components that come preinstalled in SOM's distribution framework allow messaging between objects in different address spaces on the same machine.


Figure 3: The object-distribution framework is akin to a board that fits into the SOM backplane that has some components preinstalled.

Additional components can be added (marshaling, transport, and so on) to support messaging between objects on different machines. Components also can be replaced, depending upon the particular distributed-computing environment that needs to be supported. For example, different marshaling engines, transports, or location services can be substituted for the ones supplied by IBM. Of course, if desired, the entire distribution framework could be replaced with another CORBA-compliant, distributed-object framework.

Particular installations of SOM may differ according to what frameworks and components are installed and how they are configured. It is important to note, however, that these installations do not constitute different varieties of SOM, but rather different configurations --the underlying SOM infrastructure is exactly the same in every case.

This is analogous to the almost unlimited variety of configurations available for different PC architectures (Mac, Intel, and so on). In general, different configurations run the same binary software, the differences being related to the resolution of the display or access to different peripherals. Just as you can increase the power of a PC by adding a floating-point processor or upgrading the display hardware, you can enhance SOM frameworks by adding or replacing components with ones capable of meeting the requirements---say, for example, of enterprise-wide, intergalactic, distributed-object environments.

SOM, Distributed SOM, and CORBA

SOM is a packaging technology and run-time support for the building of language-independent class libraries. SOM's distribution framework, a set of SOM classes (shipped with the SOMobjects Toolkit), allows methods to be invoked (in a programmer-transparent way) on SOM objects that exist in a different address space from the caller.

With SOM, IBM is striving to achieve many of the same objectives that the Object Management Group (OMG) aspires to with its Common Object Request Broker Architecture (CORBA) specification. Their common goal is to facilitate the interoperation of objects independent of where they are located, the programming language in which they are implemented, or the operating system or hardware architecture on which they are running.

The distributed SOM class library is fully compliant with the CORBA spec, supporting all CORBA data types, functionality, and programming interfaces. Distributed SOM is a framework built using the SOM technology that allows developers to construct distributed-object applications. Distributed SOM does not implement a separate object model or run time, since it is built with the SOM object model and run time. Currently, fully interoperable versions of the distribution framework are available for SOM on AIX, OS/2, and Windows.

Visualize SOM as a highly optimized, single-address-space, object-request broker (ORB) that provides interlanguage interoperability and supports binary subclassing and upward binary compatibility. Using SOM, objects implemented in different languages can be combined in the same address space. SOM is fully compliant with the OMG's CORBA specification. For example, SOM classes are defined by using the CORBA Interface Definition Language (IDL), and support is available for all the CORBA data types. C-language bindings for SOM classes are compliant with CORBA (CORBA does not yet have standard bindings for C++, Smalltalk, and Cobol). SOM provides an interface repository supporting the CORBA functionality and programming interfaces.

The fact that SOM deals with object implementations distinguishes it from the narrower focus of the CORBA spec (which defines object interfaces without regard to implementation). As do other CORBA-compliant implementations, SOM extends the spec's capabilities. SOM goes beyond CORBA by supporting implementation inheritance and polymorphism, providing metaclasses that are manipulated as first-order objects, and allowing dynamic addition of methods to a class interface at run time.

How Does SOM Work?

SOM achieves cross-language interoperability by building its method-dispatch mechanism based on system-defined procedure-linkage conventions. This means that SOM follows the register- and stack- utilization conventions defined by an operating system for all programs, regardless of their implementation languages. System-linkage conventions also dictate how return values are passed from the callee back to the caller. By using the system-linkage protocol, SOM can dispatch methods independent of the language in which the executable code was written. As a result, virtually any language that supports the system procedure-call linkage conventions can use a SOM class, or can be used to implement a SOM class.

SOM accomplishes upward binary compatibility by completely encapsulating the implementation details of a class. A client calling a SOM class has no information about the size and entry points to that class compiled into its executable. Method dispatch and access to instance data is effected through a set of data structures that are computed during the construction and initialization of a class.

Two of the most important SOM data structures are the ClassData structure and the SOM method table. Because these structures are completely computed at run time, a SOM class can be modified (by refactoring the class hierarchy, moving methods up the hierarchy, or adding methods or instance data, for example) without requiring recompilation of the client code. In addition, the SOM data structures can be manipulated by the programmer at run time, giving the class implementor enormous flexibility in enhancing or controlling method dispatch.

By completely encapsulating the implementation of an object, SOM overcomes what Microsoft refers to as the "fragile base class problem"--the inability to modify a class without recompiling clients and derived classes dependent upon that class.

Method-Resolution Mechanisms

SOM supports three different method-resolution mechanisms: offset, name lookup, and dispatch. These mechanisms are distinguished by the amount of information required about the object, and by the method and method signature known at the time the client application is compiled. The more information that is known at compile time, the more efficiently the method-resolution mechanism can be used. However, having all information hardwired into the client application at compile time reduces the flexibility of the client, as well as its ability to dynamically determine the object, method, or parameters used in a method invocation. As a result, it is useful to have alternative method-dispatch mechanisms available, which may be less efficient, but more flexible.

Offset method resolution is the default mechanism for method invocation on a SOM object. It is appropriate whenever the following are all known at compile time: the method name, the method signature, and the class that introduced the method. Offset method resolution offers a highly optimized path for invoking a method. In SOM, the method tokens in the ClassData structure are actually method-resolution thunks. Using offset resolution, SOM invokes a method by simply calling the appropriate thunk with the arguments needed for the method.

Name-lookup method resolution is appropriate whenever the method signature is known at compile time, but the name of the introducing class or the method name itself is not. Name-lookup resolution is less efficient than offset resolution. However, this resolution mechanism is more flexible because the particular method and object on which that method is invoked can be determined at run time based on heuristic code in the client application.

Dispatch resolution is the least efficient (but the most flexible) of the SOM method-resolution mechanisms. Using dispatch resolution, a programmer can dynamically construct the method call on an object. Dispatch resolution can be described as a dynamic-invocation interface, whereby a request on an object can be constructed and invoked at run time. The dispatch method-resolution mechanism is appropriate if it is desired to have neither the object class, method name, nor method signature compiled into the client application code. The method name, a memory area to hold any result value produced by the method, and a data structure that contains all the arguments needed for the method, are all supplied as arguments to the dispatch mechanism. The object id is the first member of the argument list.

Comparison to COM

Comparing SOM and COM is a bit like comparing the engine of an automobile with its specifications. A car's engine is not a specification. It is the essential piece of the car that generates the vehicle's motion. Similarly, the engine's specification will not impart motion to the car, but rather must first be used to build an engine before a car can be expected to actually move. In this crude analogy, the engine corresponds to SOM and the specification corresponds to COM.

An immediately observable difference between SOM and COM arises from these disparate uses of the term "object model" as a distinction in the type of code that a developer must write in every application. With SOM, a programmer writes code that uses the object infrastructure SOM provides. With COM, the programmer must also write the code that implements many of the rules and guidelines that comprise the COM infrastructure. COM requires this code to appear in every program, regardless of whether it is written manually or can be partially automated with some development tool. Essentially, COM is a set of rules programmers must interpret and follow in order to build these components.

Although frequently discussed, COM currently lacks the cross-machine, distributed-object capabilities of SOM. At the moment, there is no "distributed COM." Microsoft plans to introduce distributed COM in their Cairo operating system slated for beta testing sometime in late 1995.

OLE 2.0, Microsoft's linking and embedding technology, is built using COM. However, Microsoft does not go to very much effort to distinguish COM from OLE 2.0 (the two are bundled together). The major reason for this is that OLE currently represents the only concrete instantiation of COM.

SOM is a complete implementation of a syntax-free, object-oriented, run-time engine--one that has been carefully engineered to have a robust binary interface completely encapsulating implementation detail. This is underscored by the fact that several C++-compiler vendors currently are using SOM for their run-time library. Object-oriented language compilers that utilize SOM as their run time are referred to as "Direct-to-SOM" compilers. Because SOM has been designed to support a broad set of OO semantics, other languages (both object oriented and procedural) can utilize the SOM run time through intermediary mapping layers referred to as SOM "bindings."

Regardless of which approach is utilized (direct-to-SOM or language bindings), the advantage to a developer is that class libraries can be built that sport robust binary interfaces. Client programs may be constructed that are derived from the classes in the library using normal object-oriented inheritance techniques without compromising the ability of the class-library implementor to make evolutionary changes in the library's internals, and without requiring all client programmers to use the same development language. In short, SOM objects are similar to the normal objects in an object-oriented programming language (OOPL), except that their binary interfaces have been made more robust and replaced with language-neutral mechanisms.

Microsoft's COM, on the other hand, while equally effective at hiding an object's implementation details, does not attempt to be a run-time engine for object-oriented programming. In fact, Microsoft questions the appropriateness of today's object-oriented programming languages for exposing the interfaces of an interoperable software component. The COM specification is a way of hiding the OOPL notion of an object and exposing instead the different abstraction called a "Windows Object."

One area in which Windows Objects differ from typical OOPL objects is that of object identity. Windows Objects are not accessed in the same way as OOPL objects. Whereas an OOPL would allow you to designate a particular object with an "object reference" (or a pointer), a programmer never actually obtains a reference to a Windows Object. Instead, Windows Objects are accessed exclusively through their interface reference (pointers), and one must obtain a separate interface pointer for each of the object's interfaces that a programmer needs to use.

For example, if an object O supports three different interfaces (I1, I2, and I3), you could obtain and use references for O's I1, I2, or I3, but never obtain a reference for O itself. If you had a reference for O's I1 and I2, the only way you could even be sure that both of these referred to the same underlying object would be to query O's I1 for a reference to I2, and then see if it was the same I2 reference you already had. In general, this is always possible because COM requires every interface to support the IUnknown protocol. The IUnknown protocol specifies three functions that should appear in every COM interface, and the first of these functions should permit you to obtain a pointer to any of an object's other interfaces.

Notice that the descriptions of COM frequently use words like "should." This is because COM is largely a set of rules that are not actually enforced anywhere. When creating a Windows Object, it is the programmer's responsibility to implement all these rules and to get them right. This is yet another difference between SOM and COM. SOM's semantics are implemented within the SOM run time, while almost all of COM's semantics must be implemented by the developer in each COM object.

In 1987, Peter Wegner of Brown University introduced some order to the OO community by suggesting a subsequently well-accepted taxonomy for classifying object systems and programming languages based on the features and programming paradigms they support. In Wegner's terminology, systems that have classes and support implementation inheritance can be properly called "object oriented," while those without implementation inheritance can be characterized as "object based." This is the significant difference between SOM and COM: SOM is "object oriented" while COM is merely "object based."

The difference in approaches amounts to the fact that SOM permits class libraries to be developed by using conventional object-oriented programming paradigms, and to offer these same paradigms to their clients. COM rejects the object-oriented notion of implementation inheritance in favor of totally different paradigms for client programming. Microsoft calls these new paradigms "containment" and "aggregation," and offers them as an alternative approach for object reuse.

Aggregation and containment are essentially manual techniques for code reuse entirely implemented by developer-supplied code. COM is not involved in aggregation or containment. It simply provides rules about what users must write.

Containment is used if a programmer wants to change some aspect of the implementation of an object. It requires the programmer to encapsulate the object to be modified with another object whose interface includes the same functions as the encapsulated object. The programmer then supplies the new behavior for functions that are to be changed and provides redispatch stubs to call the corresponding function in the encapsulated object for functions that are not changed.

Aggregation is used when a programmer wishes to add functionality to an object, but does not need to change any of its preexisting behavior. Aggregation is really nothing more than an optimized form of containment in which the programmer is not required to write redispatch stubs for each function in the object's interface. However, the ability to support aggregation must be explicitly built into a COM object by the developer, so not all Windows Objects can be used in this fashion.

With SOM, IBM has chosen to solve the fragile base class problem as opposed to constraining a developers' ability to apply widely accepted object-oriented techniques. Developers of SOM objects can employ familiar paradigms such as single inheritance, multiple inheritance, or abstract (interface-only) inheritance.

— F.R. Campagnoni


Frank, a senior software engineer for IBM's object technology group, can be contacted at [email protected].


Copyright © 1994, Dr. Dobb's Journal

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.