Ideal Interfaces

So, last time I discussed a few different approaches to implementing interfaces, though didn’t explicitly state which one is best. (Obviously this is all my opinion. I’m simply saving time and easing the wording by stating everything as fact.)

The first and most essential thing to define is the purpose of an interface: an interface guarantees the provision of a minimum set of behaviours. (Contrast with inheritance: a base class provides a minimum set of behaviours and an interface.)

Obviously, this sort of guarantee has no place in dynamically typed languages. The point of a guarantee is to provide early detection of errors in a simple manner: does this object claim to implement IMyInterface? If so, we know for certain that all the members of IMyInterface are available. Further, we know that any pointer to IMyInterface provides all the members. Otherwise, we can fail immediately.

With duck-typing, there is no need for an early guarantee. Throw in multithreading and you can’t be sure of the object type until you’re attempting to call the method, which is the earliest you could detect an incorrect interface anyway.

So now we’re only looking at statically typed languages and hence, statically typed projects. ‘Toy’ projects, while useful and important, have no need for interfaces. Small projects with only a couple of co-located developers have no need for interfaces. Large projects or distributed projects, however, absolutely require strictly controlled interfaces.

The only reasonable way to subdivide effort on a software project is to identify components and assign developers to each. As soon as you discover components, you need to define interfaces. Any interacting components require an interface, and non-interacting components are usually wasted effort. Add to this that any serious project will have further development done by people other than the original developers, and strict interfaces are the only way to exert any control.

As real life examples, both Windows and Office are huge networks of interacting components. The Windows shell, effectively every Explorer window, view or extension, is COM based. If you want to create a special object for your camera/MP3 player/card reader, create an object implementing IShellFolder. If you want to add a cascading context menu to your file type, implement IContextMenu. Need newer features? Use IContextMenu2 instead.

Of course, the name is not essential. If you want IContextMenu, you actually want 000214e4-0000-0000-c000-000000000046. If you want IContextMenu2, you actually want 000214f4-0000-0000-c000-000000000046. Most importantly, there are no language restrictions. Any language producing an executable file can implement a COM object, which is great when you want or expect other people to develop for your interfaces. In an uncontrolled context, COM interfaces are undeniably the most robust.

The next step up from COM interfaces are .NET interfaces. While it is possible to guarantee that an application running on Windows can use COM, that guarantee does not yet exist for .NET. However, the versioning of interfaces in .NET is far more robust.

In general, most of .NET is more robust than its predecessors, which is why it tends to be the best thing going around at the moment. Looking at introduction dates, it’s easy to see why: C++ came about in the early 1980′s, COM appeared about 1993 and .NET came out in 2002 but was significantly re-done for version 2.0 in 2005. That’s 25 years of research and experience in C++. All the good habits that the best development teams use in C++ have been rolled into the .NET Framework and languages. Mono support is good enough now to make it as must a cross-platform solution as C++ with some other framework.

I’ll save the full Microsoft love-in for a later post, but consider this my final word: the best interfaces about are in the .NET languages.

January 3, 2010 • Tags: , , • Posted in: Uncategorized