Steve: Developing on the Edge - On Corba, DCOM, ICE, and distributed objects in general
Steve: Developing on the Edge
Thoughts on development, Web-services, technology and mountains.
22Jun
Thu2006
On Corba, DCOM, ICE, and distributed objects in general

Michi's little critique of CORBA has been stirring up a lot of press, and some good email discussions. It has made people think.

Michi co-wrote the Advanced CORBA Programming in C++ book with Steve Vinoski. This is a lovely book; it really explains what it is and how to use it. You don't come away with the same bad feelings you would get from reading a book on, say EJB2.x, which was clearly wrong. The limitations of CORBA were more subtle.

  1. The standards group focused on IDL and a compatible API first, interop second. There's lots of historical reasons there, but today, does anyone care whether an early orb used Apollo/DCE or SunOS XRPC? A cross-orb solution from the outset would have been better
  2. The CORBA to C++ binding of the era of Advanced CORBA Programming is pretty dated. IDL strings map to #define strings, not const string classes, the generated C++ predates generics. This is exactly the same failing that COM has. It is not fundamental with the technology; the CORBA working groups and Microsoft could each update their own bindings and IDL compilers.
  3. CORBA came with too many extra complex services, some of which clearly never worked. There are other standards bodies which appear to be repeating this antipattern. We need implementation-first standards with test suites released simultaneously with the specifications, otherwise the first implementations come out without being tested properly, and the specification itself may prove to have untestable parts to it.
  4. CORBA's exception model is different. Its not quite that of C++, its not that of Java. Any attempt to map seamlessly from native faults to COM isnt going to work. But that's OK, because that isnt done.
  5. Persistent object routing turns out not to work well over time. It makes for great demos, but in practise once an object starts moving around, it becomes harder and harder to locate.

But wait a minute, what was the alternative of the time? DCOM. Let's look at that. (I would include links to the MSDN topics, but msdn2.microsoft.com is returning Server is too busy errors. Hosted on Dell junk, I guess, or someone is running a DDoS attack.)

  1. IDL mapping to C++ sucks. Yes indeed. MFC: very bad. ATL, slightly better, but not updated for six years. Last time I did it, I used xslt mappings from our constants.xml file to generate proper constatnts and not the #defines the IDL would generate. No const classes; no namespace support. This is early nineties C++ here, not modern C++.
  2. Comes with extra services, some of which never get used. Distributed Link Tracking? Sure, it comes with every NT box has it turned on, but its one of the first services to turn off at tuning-time
  3. Lacks fundamental features. Like a centralised registry of things. You can configure HKEY_CLASSES_ROOT\CLSID mappings on a machine-by-machine basis to redirect to remote DCOM bindings. Yes, that's clever. Hard code remote locations for object creation, object creation that gets called by local clients expecting local objects to be returned. I bet sysadmins and developers like fielding support call related to that. Try asking an end user over the phone whether their CLSID for excel documents is mapped to a remote factory and see if you can get any useful answer.
  4. Atrocious error handling. HRESULT is it for pure COM. OLE automation adds EXCEPINFO information, which you can get filled in by an extra call to an IDispatch interface. But what happens if you are trying to talk IDispatch over the wire to a DCOM object that your registry has bound to a remote machine, and it is the network that is failing. You cannot call IDispatch to get the info, because that will just try and talk over the wire. There is no way to get error info back from the transport layers than just HRESULTS. and that is just useless. Every time you see an IIS server print an 0x80001234-style number as its sole bit of diagnostics, you, the end user, get reminded about how bad COM/DCOM error handling is.

If you want an example of how bad this stuff can be, go use Outlook 2000, the one that would crash if the laptop went out of wireless range of the server. That wasnt even DCOM, it was DCE RPC, but it acts as a glorious showcase for why the MS stacks were no better than the CORBA ones, just more broadly used in mass market applications.

Out there in the intra-organisation land, you either have REST, relatively simple SOAP (no WSRF, WS-Eventing, etc), or something custom, invariably HTTP based or at least tunneling over port 8080. What do we have behind the firewall? A complete mess. There's the DCE based win16 app for filling in travel expenses (trams- enemy of EU employees!), there's all the SAP based stuff you have to deal with when you are a project manager, the apps that tell you your budget and how much there is left. Then there's the various web sites to do things that somehow talk behind their back to each other. And there is stuff like Jabber, which, whatever it uses, doesn't accept ::CreateFile(8) as a valid password, even though the rest of the organisation does. Its a mess. But does that matter? And if it does, what would you standardise on, if not CORBA? You wouldn't go single platform, so RMI and WCF are out, despite the benefits that single platformness gives you. That leaves SOAP, REST on HTTP, WSRF/N/Eventing, ICE, maybe XMPP.

One issue is whether distributed objects are the right metaphor for distributed computing. CORBA, DCOM, ICE, RMI, .NET remoting and WSRF all implement the idea that you are talking to instances of stateful things at the end, with operations to read/write state, and verbs/actions/method calls to tell the remote thing to do something. These protocols invariably come up against the object lifetime problem, the challenge of cleaning up instances when callers go away, without flooding the network with too much traffic to indicate client health. They also have the dealing with change problem, in which both ends of the system (assuming callbacks) have to handle the possibility that either end of the system may be suddenly replaced by an upgraded version, possibly with a changed interface, possibly with changed semantics. This is hard to deal with. REST handles it best by freezing the set of verbs to a low number, only allowing one way links, but at a price, the price of no easy mapping between REST resources and native classes, no two-way links and (currently) not very easy APIs. The question is, when will the Enterpriseys notice that this is the only thing that has been shown to work.

Comments

On 22 June 2006 at 18: 52 Stefan Tilkov commented:
I would add one extraordinarily idiotic thing that was added to CORBA rather late: the whole objects by value (OBV) stuff that was the price of getting RMI back on IIOP. This totally destroyed any reasonable cross-language support (and is IMO one of the roots even of today's O/X problems).
Re: Value Objectsreply to this thread
On 23 June 2006 at 03: 49 Michi Henning commented:
Actually, OBV is detrimental only if I create OBVs with operations. The problem then is that the operation implementation must be present on the client side, with identical semantics regardless of language, platform, and compiler. For anything but the most trivial of operations, this is difficult to ensure and does indeed destroy the cross-language architecture.
However, this is not the case for OBVs without operations. They don't have this problem because no behavior is required for them on the client side.
(As an aside, though, the CORBA C++ mapping completely ignores the issue of OBVs that contain cyclic references, which means that, every time I receive or send a graph of objects containing a cycle, all the objects in the cycle, plus all the objects pointed at by objects in the cycle, are leaked.
Cheers,
Michi.
We can do better than previous middlewarereply to this thread
On 23 June 2006 at 04: 06 Michi Henning commented:
Hi Steve, just a few comments from me...
> Persistent object routing turns out not to work well over time. It makes for great demos,
> but in practise once an object starts moving around, it becomes harder and harder to locate.
This is true for CORBA's implementation repository because the repository address is written
into each indirect IOR, and there is no way for the CORBA run time to distinguish a direct
IOR from an indirect one. In turn, this makes migration of objects a big problem if
they need to migrate across a location domain boundary.
But it need not be that way. CORBA's location transparency has really two flaws:
- The address of the repository is written into each IOR.
- Support for location transparency is built into IIOP.
The first point causes the problem I just outlined with respect to object migration.
The second point means that it is impossible for mere mortals to replace the CORBA
location mechanism with a better one, because doing so requires modifications to IIOP,
as well as an ORB's source code.
Ice solves the problem differently. For one, it does *not* write the address of the
location broken into its proxies. Instead, the location broker's address is known
to the run time via a configuration parameter. This means that, conceptually,
Ice's location mechanism works like the DNS: the DNS server's address is externalized
into resolv.conf so no programs break if the DNS server has to change.
Secondly, Ice does not have any protocol support at all for location transparency.
Instead, the Ice run time uses ordinary IDL-defined operations to resolve the address
of a remote invocation at run time. This is not only simpler, but also means that anyone
can replace the Ice location mechanism with one that is more to their liking without
breaking a single line of code or configuration.
> One issue is whether distributed objects are the right metaphor for distributed
> computing. CORBA, DCOM, ICE, RMI, .NET remoting and WSRF all implement the idea
> that you are talking to instances of stateful things at the end, with operations
> to read/write state, and verbs/actions/method calls to tell the remote thing to do something.
Minor comment here: CORBA can be just as stateless as any other technology. It leaves
the choice as to whether to be stateful or stateless to the application designer.
True, the majority of CORBA applications are built with stateful interactions between client
and server, with all the disadvantages and advantages that implies. But I can build
stateless things just as easily (also with all the disadvantages and advantages that
implies).
> These protocols invariably come up against the object lifetime problem, the challenge
> of cleaning up instances when callers go away, without flooding the network with too
> much traffic to indicate client health.
For stateful interactions, yes that is true. And the DCOM approach of using distributed
GC cannot possibly scale (as MS finally admitted after three failed attempts to make it
scale). But there are other well-known patterns for dealing with the problem pragmatically,
cheaply, and effectively, with very little programmer effort. I wrote an article in our
newsletter about this recently, "The Grim Reaper: Making Objects Meet Their Maker":
> They also have the dealing with change problem, in which both ends of the system
> (assuming callbacks) have to handle the possibility that either end of the system may
> be suddenly replaced by an upgraded version, possibly with a changed interface, possibly
> with changed semantics.
Ice provides an elegant and cheap mechanism to deal with the versioning problem without
breaking the client-server contract. I wrote another article about this in our newsletter,
"Can a Leopard Change its Spots": http://www.zeroc.com/newsletter/issue8.pdf
Ice facets (which provide the mechanism) are not a panacea for all versioning problems, but
go a very long way toward making graceful upgrades of distributed applications a painless
process. They are certainly a far better option than CORBA's ostrich approach to versioning...
Cheers,
Michi.
distributed objects == anti-patternreply to this thread
On 23 June 2006 at 15: 56 RogerV commented:
Distributed objects should be regarded as the greatest anti-pattern of software design that has ever been foisted. Untold bad implementations and bad technology initiatives have resulted from this one classic anti-pattern. But people to this day continue to latch onto it with bulldog tenacity.
The network is neither reliable or deterministic. Get over it.
Asynchronous messaging remains the only pragmatic way to go about implementing distributed software systems. But you have to shift your mindset out of a host of bad inclinations that comes from wanting to try and use your objects directly over the network.
Technical Standards Digressionreply to this thread
On 26 June 2006 at 15: 05 Carlos Perez commented:
"Technical standards digress in proportion to technological progress"