Better to write your .NET library with COM limitations in mind, or separate your .NET library from Interop?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/277256

  •  07-10-2020
  •  | 
  •  

Question

I came across this interesting article: How I Came to Love COM Interoperability on CodeProject, which got me thinking...

The author argues that they do not want any COM-ities in their .NET library because it takes away from the beauty of their .NET library. Instead, they'd rather write a separate Interop library that exposes their .NET library to COM. This Interop library would handle the fact that COM doesn't support Constructors with Parameters, Overloaded Methods, Generics, Inheritance, Static Methods, etc.

And while I think that is very novel, doesn't it just complect the project?

  • Now you need to unit test your .NET library AND an Interop library.
  • Now you need to spend time figuring out how to work around your beautiful .NET library and expose it to COM.
  • You need to, effectively, double or triple your class count.

I can certainly understand if you need your library to support both COM and non-COM. However, if you only intend to use COM does this sort of design bring any benefits that I don't see? Do you only gain the benefits of the C# language?

Or, does it make versioning your library easier by providing you a wrapper? Does it make your Unit Tests run faster by not requiring the use of COM?

Was it helpful?

Solution

However, if you only intend to use COM does this sort of design bring any benefits that I don't see?

This snippet of your question is the most important part of your design decision here, and the answer is (as always) it depends.

If you only intend to use the library via COM Interop, then you should design the entire system with this in mind. There is no reason to triple the line count. The more LoC in the system, the more defects it will have. You should therefore design your system to only use COM compatible functionality.

However, I can't think of a good reason to restrict the use of a .Net library to COM. Why wouldn't you want to be able to use the assembly in other .Net code? It makes little sense to limit yourself this way.

I have some experience with this, so I will share how I have handled it. Its certainly not ideal. I have made some trade offs. I only use a facade for COM classes (interfaces really) that are incompatible with the newer .Net idioms, otherwise, I directly expose the .Net interface to COM. This basically means that I use a facade for any interface that uses generics. Generics are the only thing I've come across that are just simply incompatible. Unfortunately, this means a facade for anything that returns an IEnumerable<T>, which is fairly common.

However, this isn't nearly as bad as it seems to be, because your facade class inherits from your .Net class and implements a specific Interop interface. Something like this.

namespace Company.Product.Feature
{
    public class MyClass : INetInterface 
    {
        // lots of code
    }
}

namespace Company.Product.Interop
{
    public class MyClass : Feature.MyClass, IComInterface
    {
        // over ride only the  incompatible properties/methods
    }
}

This keeps your duplicate code to an absolute minimum and protects your COM interface from "unintentional" changes. As your core class/interface change, your adapter class has to over ride more methods (or break the interface and bump the major version number). On the other hand, not all of your Interop code is stored in the Interop namespace, which can lead to a confusing file organization. Like I said, it's a trade off.

For a full blown example of this, you can browse through the SourceControl and Interop folders of my repo. ISourceControlProvider and GitProvider will be of particular interest.

OTHER TIPS

it takes away from the beauty of their .NET library

That author needs a wake-up slap to the face. For any professional project, the goal is to make working software that people want to use. Any kind of misguided ideals about beauty come long after that. If that's their only reasoning, the author has lost all credibility.

Being able to mark your classes as com-visible and being able to talk to your .NET code through COM is enormously useful. Discarding that great benefit to productivity for beauty is insane.

However, making things work with COM does require some trade-offs, requiring a no-arg constructor is one of them, and some of the other stuff you mentioned. If those are features you aren't using anyway, or it won't hurt you to not use them, then there is a lot of work to be saved by using the same class for COM and non com.

On the other hand, if your COM clients expect a dramatically different interface, has dependencies or other limitations that are nasty to deal with in your .NET classes, or you expect to be significantly changing your .NET classes and need to maintain COM backward-compatibility, then by all means create an Interop class to bridge that gap.

But don't think about "beauty". Being able to expose COM through .NET is meant to save you work. Don't create more work for yourself.

Well, to be fair, the original author of that article did not use the word "beauty" anywhere in his article, that was you, which might give a biased impression on that for those who did not take the time to read the article by themselves.

As far as I have understood that article, the .NET library already existed and was written without COM in mind - probably because at the time when the library was created, there was no requirement to support COM.

Later on, the additional requirement of supporting COM was introduced. Facing such a situation, you have two options:

  • redesign the original lib to make it compatible with COM interop (with the risk of breaking things)

  • let the original working library mostly as it is, and instead create a separate assembly with the function of a "wrapper" (or "adapter")

Creating wrappers or adapters is a well-known design pattern (or in this case more an architectural pattern), and the pros and cons are also well known. One argument for it is the better "separation of concerns", and that has nothing to do with beauty.

To your concerns

Now you need to unit test your .NET library AND an Interop library.

When you introduce your COM interface to your existing .NET library by redesign, you have to test that interface either. Introducing a manually written adapter may need some additional tests that the interface is working, of course, but there is no need to copy all unit tests of the core business functionality of the lib. Don't forget it is just another interface to the lib.

Now you need to spend time figuring out how to work around your beautiful .NET library and expose it to COM.

When you have to redesign the original library you have to figure that out, too, and I guess it will be much more work.

You need to, effectively, double or triple your class count.

Only for the classes which are exposed through the public COM interface, which should be a small number of the classes part of the original library.

Said that, for a different situation you mentioned, when you already know you have to support COM as a first-class citizen right from the start, I think you are correct: one should save the hassle of adding a separated adapter lib and design the .NET lib with COM support directly.

Licensed under: CC-BY-SA with attribution
scroll top