On Being Object-Oriented: COM and CORBA
David Chappell - April 1997
What does it mean to be object-oriented? And what are the characteristics
that make a technology qualify as object-oriented? Asking these
questions is a little like asking about the meaning of life: there's
no single answer that everyone agrees on. But I think most people
would agree that, whatever the meaning of life, being object-oriented
requires a few common elements.
Among the most important are: viewing things in terms of objects, discrete combinations of code and data; having some kind of life cycle for those objects, allowing their clients to create and destroy them; organizing object instances into classes; and providing support for encapsulation, polymorphism, and inheritance.
I'd like to compare the way in which COM and CORBA define and use objects, organizing the comparison according to the criteria just listed. Along the way, I'll demonstrate that, contrary to what you might have read, COM is every bit as object-oriented as CORBA.
Both COM and CORBA define objects in the conventional way, as collections of methods and data. Both allow access to an object only through specific interfaces, and both provide an Interface Definition Language (IDL) that can be used to define that interface. In CORBA, each object presents a single interface to its clients, and each client holds one object reference to the object as a whole. In COM, on the other hand, an object can (and almost always does) present two or more interfaces to its clients, and a client commonly holds multiple interface pointers to the same object. Unlike CORBA, COM clients invoke methods through a specific pointer to the interface containing that method rather than via a single reference to the entire object.
The idea of an object that presents many interfaces can seem odd to some people, and it's one of the reasons that COM has been criticized as not being truly object-oriented. Java takes this same approach, however, allowing one object to present multiple distinctly identifiable interfaces to its clients. Furthermore, the ability to support more than one interface is being added to CORBA, making it even harder to argue that it's somehow non-OO.
Creating and Destroying Objects
To use an object, it must first be created. In COM, a client can create an object via a call to the standard COM library. Among other parameters to this call, the client specifies the class identifier (CLSID) of the kind of object it wants to create. To efficiently create many objects of the same class, a client can instead acquire a pointer to a class factory for that class. However it's done, a client gets its first interface pointer to a new object as part of the creation process. It then gets any other pointers it needs by asking the object for them directly. When the client is finished using any interface pointer, it informs the object of this fact by calling the Release method on that pointer. When all clients have released all pointers on all of an object's interfaces, that object usually destroys itself.
In CORBA, an object is typically created by a call to the ORB. This call generates an object reference for the new object, a reference that can be used by clients to invoke methods on the object. A client can also use a somewhat loosely defined entity called a factory object to create objects, not unlike COM. While there are significant differences in how the two technologies view the process of creation, the broad outlines are much the same.
When a client invokes a method on an object that's currently active (i.e., the object's code and data are in memory), the ORB passes the request to the running object. If the target object is not currently active, the ORB loads it, then hands it the client's request. Clients need not inform an object when they are done using it, and exactly when an object stops running is not defined by the CORBA standard-different products do it differently. In CORBA, unlike COM, causing an object to stop being active is not the same thing as destroying it. Instead, CORBA requires some client to explicitly tell the ORB that an object should be deleted. Until this is done, the ORB is perfectly willing to start and stop the object as needed.
More on Classes
A class is usually thought of as a template for objects, one that defines the methods and data types of each instance. In CORBA, an object's class is essentially defined by its interface. Each object has one interface (today, at least) that defines the methods visible to its clients. Since interfaces specify only externally visible things, they don't define an object's data, although they may contain attributes, which generate methods that get and set specific data values.
COM's notion of class doesn't exactly fit this common definition. The CLSID a client specifies during object creation ultimately maps to a particular file to load, controlling what code runs for this object. It does not, however, necessarily indicate what interfaces the newly created object supports. It's possible to create an object using a particular CLSID one day that supports interfaces A, B, and C, then create an object using the very same CLSID the next day, only to find that the object now supports interfaces X, Y, and Z. The CLSID is mapped to a filename, and if that filename is changed, the interfaces the object supports may also change. Changing your class registry is this way is almost certainly a bad idea-I recommend against it-but it's not illegal. From the perspective of most other object technologies, COM's notion of class is a little loose.
The Magic Words
To qualify as truly object-oriented, a technology needs to provide encapsulation, polymorphism, and inheritance. COM and CORBA both provide encapsulation, and they do it in just the same way: by allowing clients access to an object only through the object's interface(s). Similarly, both technologies provide polymorphism, the ability for different kinds of objects to respond appropriately to the same message. Once again, interfaces are the ticket. By allowing different classes to support the same interface (or even some of the same method definitions) while implementing the methods differently, COM and CORBA allow an object's clients to remain blissfully unaware of differences that need not concern them.
It's in the third aspect of object-orientation, inheritance, that COM and CORBA's object models are widely believed to differ from one another. In fact, however, this is not true. Both COM and CORBA support interface inheritance, the ability for one interface definition to inherit from another. But neither COM nor CORBA specifies support for implementation inheritance, the ability for one object to actually inherit code from another. IBM's implementation of CORBA, embodied in their System Object Model (SOM), does support implementation inheritance in some cases, but the CORBA spec in no way requires this. In fact, the great majority of CORBA-based products support only interface inheritance, just like COM.
How can this be true? Countless articles, newsgroup postings, and hallway conversations have rehashed the claim that COM doesn't support inheritance. If what's meant here is implementation inheritance, this statement is absolutely true, and it's true of the CORBA standards, too. If what's meant is interface inheritance, however, it's entirely false. Exactly how this canard gained such currency is lost on me. The only explanation I can think of is that it's so tempting to believe that Microsoft, the company that gave us MS-DOS, must not be capable of doing anything right. But in fact they have done at least a few things right, not the least of which is producing a powerful, effective, and yes, object-oriented technology in COM.
Reason and Emotion
Perhaps like you, I've read countless criticisms of COM, many of which made the claim that COM wasn't really object-oriented. Often, these articles were rife with factual errors-the authors didn't understand COM. (In fact, almost all of the interesting COM critiques I've run across have come from Microsoft people, since they're the ones with the best understanding of the technology.) Many, perhaps most, of these ill-informed attacks weren't really about making technical points, though. Instead, the subtext of each was the same: it was "I hate Microsoft". While hating Microsoft may in fact be a valid thing to do-it's a free country-it should not be confused with making reasoned technical arguments. The next time you see an attack on COM (or for that matter, on anything), I encourage you to ask yourself whether the writer is making rational, accurate statements or just expressing disguised emotion. Reading emotional articles that support your biases will make you feel good at the time. But improving your understanding of reality, something that only new and accurate information can make possible, will unquestionably make you happier and more successful in the long run.