A few years back when I first started reading about design patterns, refactoring, OO principles etc. I got it into my head that I should “Always program to an interface not an implementation”. So whenever I needed to create a new class/abstraction I used to start of with an interface IThis, IThat etc. over a period of time I saw that most of my interfaces were only ever implemented by one class. This started becoming a pain to maintain as adding a new method meant that the method needed to be added to both the interface and the implementation class, further since there was only one implementation of the interface some developers started substituting one for the other and freely casting between the interface and the implementation. This became a source of constant code review changes and eyesores in code, with some methods expecting interfaces and others expecting the implementation class. Of course with strict code reviews we would never have got into this situation, but I’ve been working in startup companies all this time where getting something out there to earn $$$ has much higher priority than clean code.
Over the last few months I had to introduce some new features into our product which required that an abstraction that previously only had one implementation should now have 3, this was one of the cases where the class did not implement an interface. Contrary to what I had expected, refactoring the class and extracting an abstract class from it which was then subclassed by the different implementations lead to a very clean and satisfying design. This experience has taught me that unless you are writing code that interacts with something that is not under your control (a component or library for e.g.) it’s never a good idea to start with an interface.
On the other hand another feature that required extending an interface that was already defined became a big mess as a lot of the methods did not have a reasonable implementation under the new scheme and had to throw NotImplementedException’s. It was also difficult to refactor the interface as there were a huge number of dependencies. This could have been avoided if the Interface had been extracted on a need to need basis, further this would have lead to much more granular and cohesive set of interfaces rather than one huge bloated interface.
Starting with an interface on inward facing code means that you are making certain assumptions about how your code will evolve, in my experience these asumptions are almost always wrong and you end up supporting an interface that was never required in the first place. So now I start off with a concrete class and extract interfaces from the class as and when required, this has lead to much cleaner code and reduced the overhead of redundant definitions.
What have been your experiences in this matter?