Hacker News new | past | comments | ask | show | jobs | submit login

COM is a necessary evil when integrating with Windows, Office, Visual Studio, or any other big/old Microsoft product. That's just how it works.

The .NET framework actually does a pretty good job of hiding the complexity from you, but having done some serious integration with VS, let me say that's an abstraction leak that I wouldn't wish upon my worse enemy.




I never thought the .NET Framework did enough complexity hiding to justify a 60MB installed size, especially if it was just providing a bit of plumbing to get you back down to the COM level.

Most COM interfaces support late binding, so you can easily call them from a language like JavaScript, which is already installed in Windows as part of the platform. Ten years before node.js existed, you could run this JavaScript on Windows 2000 to read and print a file:

    var fso = new ActiveXObject("Scripting.FileSystemObject");
    if ( fso.FileExists("myfile.txt") ) {
       var ts = fso.OpenTextFile("myfile.txt", ForReading);
       WScript.Echo(ts.ReadAll());
       WScript.Quit(0);
    } else {
       WScript.Echo("File Not Found");
       WScript.Quit(1);
    }


Well, that's a facetious argument if I've ever seen one :). .NET does a lot more than just interface with COM or the Windows API. VB (pre .NET days) had much better integration with OLE/COM and the runtimes were like 1mb in size at worst.

I've always thought of COM as one of those almost brilliant pieces of technology that somehow got completely ignored. Of course, it's still commonplace in the Windows world, but the concept facilitates reusability so much, it's a shame it wasn't adopted by other platforms.


I think Mozilla used something similar in Firefox: https://developer.mozilla.org/en-US/docs/XPCOM

Other than that I don't know any other companies who did something like COM.


The .NET framework is more than just a bit of COM plumbing.


Where have you found the abstraction leaky? I've generally found it works just fine; the only leaky part of it I've found is in some of the Microsoft-provided .NET wrappers, which I've seen leak memory. (Directly using the COM objects works around that 100% of the time for me.)

Edit: I'm not really being clear above. When I'm saying I've found the leaky abstraction to be around memory management, I'm not conflating "leaky abstractions" with "memory leaks," except insofar as the big point where I find problems with COM is around the need to be much more explicit with resource management. That the leaky abstraction happens to be around the...er, leaks, is coincidental.


Leaky abstractions have nothing to do with leaking memory. A leaky abstraction is a layer that attempts to reduce complexity and fails at its job by not hiding enough of the ugly parts.

It's a Spolsky-ism: http://www.joelonsoftware.com/articles/LeakyAbstractions.htm...

Edit: Egg meet face.


I actually work at Fog Creek for Joel; I just happened to pick an absolutely horrid way to phrase what I was trying to convey. (I edited the original post to clarify.)

The memory management is the part of COM that leaks through the abstraction layer in my experience, but it has usually leaked through in MS's attempt to actually properly jacket the things in full-blown .NET objects. I've otherwise not had issues.

I have a hunch I'd also complain about the remote proxying if I used DCOM from .NET, but I haven't.


I think the parent means that it's a leaky abstraction because normally the GC takes care of deallocating memory of CLR objects but it can't help you with native code.

Also, parent works for Fog Creek.


The average consumer of Microsoft code instantiates a few objects and calls a few methods. That, for the most part, works extremely well. Memory management, as you mention, is a big pain point because you immediately are faced with reference counting. However, by itself, that's not a big issue.

Things go crazy once you decide that you want to give your COM object to somebody else in a framework-style callback pattern. For example, if you want to extend Visual Studio, you need to implement a bunch of interfaces, manage memory yourself, deal with object registration and GUIDs, worry about invalid interfaces and versioning, etc. And that's just all the standard COM stuff, that you're faced with 100% of the time.

But there are compounded complexities. COM uses HRESULT return values, .NET uses exceptions. Most public interfaces quickly start looking like dynamicly typed code: full of references to IUnknown and QueryInterface calls. You need to understand all the threading apartment model stuff, but the .NET libraries bundle up some best practices there that often don't play nice if you need to slightly bend the rules.

Finding documentation is impossible because the web is dominated by low quality questions with low quality answers using the same terminology. Using the Microsoft personas, the Morts and Elvises drown out the Einsteins in the Google results. However, even having the VS source (which I did), it's far too big to grep and far too many levels of QueryInterface indirection to grok.

Need some enum values? You'll need to redefine them yourself. Go find the C headers and copy out the values.

Need to deploy a new version? Good luck understanding the rules of AssemblyVersion, AssemblyFileVersion, the class loader, Locales, etc. Some random error happening somewhere in the class loader? You need to install some little utility program that some guy in DevDiv made that makes a secret registry key set up some secret logging to some secret IPC channel. Argh.

I was tasked with wiring up deploy/debug for WinPhone 7. I needed to implement a few dozen methods from the IVsDebugger interface, do all my own threading and networking, and then spend a few weeks debugging synchronization issues with the UI. Meanwhile, I had the exact same task for Familiar Linux on a Compaq iPaq several years prior to that. Despite Eclipse's bloat rivaling Visual Studio's, all I needed to do was change a config file from `$PROG $ARGS` to `ssh $HOST gdb $PROG $ARGS`.

EDIT: Just wanted to add that I found this post difficult to write. I, for the life of me, couldn't recall the interface name IUnknown. In the 3 years I've been gone, I've forgotten more about COM than most .NET programmers will ever know. I'm quite happy about that...both for me escaping, and for those .NET programmers lucky enough to remain ignorant of these things. In general, all of DevDiv does a great job keeping this complexity away from people writing line of business applications.


Okay; I get why we're having different experiences.

When I'm writing managed code that needs to work heavily with COM, I write it in C++ using ATL, and expose that a level higher for calling from .NET. This avoids 90% of the issues you're hitting, while making it trivial to use COM from .NET (or, for that matter, any other non-C++ language).

The good news is that WinRT does legitimately solve most issues managed languages have. To me, far more importantly than WinRT's ability to export full-blown classes, is its ability to export much, much richer metadata, providing a straightforward way to work with WinRT objects from any language that can process the new metadata format. No more secret enums in header files, no more HRESULT insanity (HRESULTs are transparently mapped to exceptions). Just clean, cross-language calling. We've finally realized the original promise of COM.

Of course, that goal was met by "cheating." In my opinion, Microsoft achieved their goal merely by pushing the abstraction layer further into C++. In practice, I think that's an overall win--it certainly makes most of your points about using COM from managed languages moot--but it also means that your "native" libraries are going to be significantly more WinRT-specific. Or, if you prefer: instead of writing an ATL jacket to make the COM interface clean for .NET, I'll instead write a WinRT jacket to make a C++11 library clean for .NET.

The more things change...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: