Interfaces - necessary, but not sufficient

Using an interface seems like one of those rules.  Everybody knows they should do it, because it makes your code more abstracted and… stuff.

However, if you have a gigantic class with a ton of methods, or methods that are very specific to its implementation, then simply providing an interface that mirrors the public methods of the class is of little value.  To successfully swap one implementation for another, you would need to understand the behavior of the first implementation so well that you could accurately mimic it - and, frankly, that’s not very likely unless you’re the one to write the first implementation anyway (and probably not too likely even then).  While you’ve avoided implementation coupling, you’ve got a kind of conceptual coupling in its place.  This is doubly true if the interface specifies that it returns objects that implement another interface (likely as thick as the first).

So, using interfaces as kind of headers doesn’t really help us too much in this case.  We’re still realistically tied to an implementation, and now we have interface versioning issues to deal with (which, for C# at least, are worse than class versioning issues, as adding a member to a class does not break backwards compatability - but it does for an interface).

That doesn’t mean that I’m against interfaces.  In fact, I love interfaces.  I just think that there’s better ways to use them than as sim-headers.

Interfaces should be used to define questions that, as the class you’re writing, you want to ask of your dependencies.  This is a bit of an inversion - typically, interfaces are defined from the POV of the class implementing them, not the class using them.  But, by controlling the interfaces you use, there’s less chance of them breaking and causing major headaches throughout your codebase.

Interfaces should also be as small as possible, and represent a single aspect of what you can do with an object.  IEnumerable<> is a great example - it only lists things that you need to do to enumerate a collection.  And because of that, it can be very stable.  The more things an interface does, the more likely it is to need to change, and the more code that will be broken when it does.

So, if you’re using interfaces in this way, how do you implement them?  Especially if the class you’re dealing with didn’t own the interface to begin with?  This isn’t too hard - write a small adapter class that implements the interface, and calls the underlying object in the appropriate way.  This has the added advantage of keeping all your dependent code in one spot, making it much, much easier to fix if the dependency ever changes underneath you (assuming that you don’t control it).