Here’s a personal bete noir. Interfaces are good m’kay? They allow you to separate function and implementation, you can mock them, inject them. You use them to indicate roles and interactions between objects. That’s all smashing and super.
The problem comes when you don’t really have a role that you are describing, you have an implementation. A good example is a Persister type of class that saves data to a store. In production you want to save to a database while during test you save to an in-memory store.
So you have a Persister interface with the method store and you implement a DatabaseStorePersister class and a InMemoryPersister class both implementing Persister. You inject the appropriate Persister instance and you’re rolling.
Or are you? Because to my mind there’s an interface too many in this implementation. In the production code there is only one implementation of the interface, the data only ever gets stored to a DatabaseStorePersister. The InMemory version only appears in the test code and has no purpose other than to test the interaction between the rest of the code base and the Persister.
It would probably be more honest to create a single DatabaseStorePersister and then sub-class it to create the InMemory version by overriding store.
On the other hand if your data can be stored in both a graph database and a relational database then you can legitmately say there are two implementations that share the same role. At this point it is fair to create an interface. I would prefer therefore to refactor to interfaces rather than program to them. Once the interaction has been revealed, then create the interface to capture the discovery.
A typical expression of this anti-pattern in Java is a package that is full of interfaces that have the logical Domain Language name for the object and an accompanying single implementation for which there is no valid name and instead shares the name of the interface with “Impl” added on. So for example Pointless and PointlessImpl.
If something cannot be given a meaningful name then it is a sure sign that it isn’t carrying its weight in an application. Its purpose and meaning is unclear as are its concerns.
Creating interfaces purely because it is convenient to work with them (perhaps because your mock or injection framework can only work with interfaces) is a weak reason for indulging this anti-pattern. Generally if you reunite an interface with its single implementation you can see how to work with. Often if there is only a single implementation of something there is no need to inject it, you can define the instance directly in the class that makes use of it. In terms of mocking there are mock tools that mock concrete classes and there is an argument that mocking is not appropriate here and instead the concrete result of the call should be asserted and tested.
Do the right thing; kill the Impl.
4 thoughts on “Programming to Interfaces Anti-Pattern”
I agree sometimes to use interfaces is an overkill when you have only one reasonable implementation, but I don’t like the example you’re using (the persister one). I like having the persistence layers isolated from the rest of the application and I like having a non-technological-dependent name for the INTERFACE. I think that DAO pattern is one of the more useful. It’s nice having your application ready to deploy in different clients with different persistence options by changing the injection of the implementation instance.
I also agree that “If something cannot be given a meaningful name then it is a sure sign that it isn’t carrying its weight in an application”, but sometimes you don’t have option… Think about RMI or other situations where you need to apply the proxy pattern because of technology limitations.
I prefer the Repository (http://martinfowler.com/eaaCatalog/repository.html) pattern to DAO, DAO seems too leaky. It kind of implies that you will be accessing data; maybe, maybe not, backends come in all kinds of flavours these days, you might actually be using a service to fulfil the request.
I agree that you cannot do much about legacy implementations like RMI or EJB (1, 2) except to pretty them up. However I have encountered this anti-pattern more than I have encountered applications that actually use RMI.
Hi – I know that you wrote this post a few years ago. I’m curious as to whether your thoughts on this have changed at all. While I certainly agree with your rule-of-thumb concerning impl, I tend to disagree with your example concerning persisting of objects. I believe that we should separate major architectural boundaries (persistence, interface ect) with an interface even if that interface is only implemented by one class in the production environment.
In my opinion, the ability to inject an in-memory persistence stub or a simulated web stub that implement these interfaces make it much easier for us to add new code and quickly run our tests without the need hit a spinning disk or a web interface is worth the slight obfuscation of our code and the idea of sub-classing just doesn’t feel right to me.
I’m not saying that I’m right but I am interested in your opinion as I am always interested in opposing points of view on this stuff. Cheers, Rich.
I think one of the biggest changes since I wrote this post is that I’ve more or less abandoned object-orientated style programming in favour of functional style programming. OO is now mostly reserved for job interviews. My answer to testing or boundary implementations is now highly influenced by functional composition. A function definition allows many implementations without the complication of defining interfaces or class hierarchies.
I think what you describe in your example is exactly how you create pluggable extensions in an OO-language but even in your example there must be two implementations of the interface, the test implementation and the production implementation. I wouldn’t think it is a good idea to create a theoretical interface without having multiple implementations. I don’t believe it would be hard to refactor to an interface and then implement it immediately when the genuine need arose.
As a final point I have major doubts about the value of in-memory implementations for testing. Their fast performance characteristics can be incredibly misleading compared to production and in general I think it is easier to assert “correctness” by looking at the output of functions than trying to track the internal state of a collection of objects.
Thanks for commenting.