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.
Modeling Objects
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.