COM, the Component Object Model has essentially 3 aspects:
What do these aspects have in common? Why were these unrelated features ever combined?
To share object behaviors across disparate languages that treat RTTI and lifetime management differently.
For example, C++ has dynamic_cast which uses compiler-generated RTTI, and has delete. In contrast, Visual Basic has a different set of dynamic casting operators and is garbage collected (no delete). And if objects have special destruction semantics then they could have special construction semantics, hence the need to include factories in that mix.
If you want an object to work in both languages, it has to provide a cross-language solution for RTTI and lifetime management.
That's why COM has both: to share classes and objects (especially their methods) across languages.
But if you're writing strictly C++ code, why bundle these aspects into one technology?
Why not just use shared_ptr or intrusive_ptr separately from an RTTI solution?
I can see why you would want to roll your own RTTI solution involving something akin to IUnknown, QueryInterface, and GUIDs -- because compiler-generated RTTI bloats executable size by injecting type info for classes where you do not use a dynamic_cast. Using QueryInterface+IUnknown lets you confine that to the classes that require it. (Although read this opinion about custom RTTI.)
I can almost see why you'd combine RTTI with factories -- because both interface discovery and factories need to use a type identifier. They do not need to share identical type identifiers, but you might as well share them. Still, sharing info differs from providing both solutions in the same package.
But In a single-language context, I know no compelling reason to merge all three in a single package.
Combining them violates the Single Responsibility Principle -- and that's bad architecture.
I've seen situations where people want interface discovery (RTTI) so they leap to proprietary COM implementations.
Why do smart people reinvent COM-like technologies for use within a single language? Why not keep the three aspects separate?
Saturday, December 17, 2011
Subscribe to:
Post Comments (Atom)

2 comments:
If I remember the Gamebryo object structure correctly (do you know if FIEA is still using it, or moved on to some other engine?), they carefully separated RTTI and reference counting, but their insistence on single inheritance meant that they had to make an architectural choice: one of those two had to come in a parent class, which meant that one of those two implied the other.
(The inheritance cascade looked something like MemObj (buy into their allocator) -> RefObj (buy into their reference counting) -> Object (buy into their RTTI + serialization); you could have reference counting, but if you wanted RTTI you must also accept reference counting.)
Ah, good for them, keeping RTTI separate from ref counting, at least at the top-most layers.
I can appreciate the desire to use only single inheritance, at least for implementations. (It's okay to inherit multiply from interfaces.)
It sounds like they made it *convenient* to get both together, but they didn't *require* it.
(Not sure if FIEA still uses Gamebryo. Each year I was there, FIEA used different game engine technology, and I think that was wise -- to explore the range of possibilities.)
Post a Comment