I often see that following dependency inversion principle (from SOLID) we end up with many interfaces with just one implementation, and what is more it’s usually whole public API of given class. In my opinion it doesn’t make sense. However I do believe in original purpose of this rule. Like the example of deploying embedded system, when you can recompile and send through wire less data because you applied interface.
So, we should avoid interfaces with one implementation, right?
From my experience interfaces with one implementation should be avoided. I sometimes hear this explanations from people adding interface with one implementation:
- when I have inerfaces (even with one implementation) code is decoupled – seriously? Adding interfaces changes anything? In my opinion no. If there is need for coupling and there is coupling in real life then it probably should be depicted in the code.
- when I have inerfaces (even with one implementation) testing is easier – I can agree with that, however when I saw code people stating that in tests I did not see implementation of this interface Like RepositoryInterface and InMemoryRepository implements RepositoryInterface, and what they do is just creating another mock with mocking library
- when I have inerfaces (even with one implementation) when I will need second implementation it will be easier – happend zero times in my over 10 years experience. Usually abstraction that you will make based on one case won’t fit more cases. That is why I propose to wait with creating abstractions till you will be able to notice the pattern (at least 3 cases)
- when I have inerfaces (even with one implementation) it isolates parts of the system – I can sometimes agree, but usually what I see is the interface that contains whole public API of given class and what is more is changed with the same pace as given concrete class (bruh)
So what’s wrong with interface with one implementation?
In my opinion the less code we write the better, so I don’t like interfaces with one implementation because:
- they make navigation trough code harder,
- you have more code,
- they hide real dependency even if there is only one implementation
So when to use interface?
From my experience creating abstraction is really hard. That is why I advice to wait till more cases, so you can notice and validate pattern. In general I think that creating interfaces with one implementation is misinterpeetation of DIP from SOLID, here is quote from Uncle Bob:
The need to mock every class interaction forces an explosion of polymorphic interfaces. In statically typed languages like Java, that means the creation of lots of extra interface classes whose sole purpose is to allow mocking. This is over-abstraction and the dreaded “design damage”.
https://blog.cleancoder.com/uncle-bob/2014/05/10/WhenToMock.html