Keeping interfaces and implementations separate is a useful design pattern for building modular systems. If your clients only depend on a service interface, you can switch service implementations without your clients even noticing.
Now there can be too much of a good thing, and the quality of a software system is certainly not measured by the ratio of interfaces to classes.
When you are planning to implement a
FrobnicatorService, think twice before creating an
IFrobnicatorService interface and a
FrobnicatorServiceImpl. How many different
Frobnicator implementations are there going to be? If you do need at least two implementations with distinct behaviour, then go ahead and create the interface. If there's only one implementation, then don't bother with the interface.
Resist the temptation of speculative generalization: "Oh, there might be a performance bottleneck, and in that case an alternative
CacheingFrobnicatorServiceImpl might help, so I really should start with a service interface now." Think twice: you ain't gonna need it.
And if you do need the interface, you can still pull it out
when you need it. Most IDEs have an automatic refactoring
Extract Interface. (Unfortunately, none of the major Java IDEs seems to have the opposite refactoring
Merge Interface and Implementation.)
Even in Java EE, the times of interface inflation are gone with EJB 3.1, thanks to the no-interface local view. For a stateless session bean, it is enough to implement
@Stateless
public class FrobnicatorService {
public void frobnicate() {
...
}
}
Every public method of this class will be part of the implicit local business interface.
In OSGi, a service does not need to have a separate interface, you can register any class as a service. Even when using Declarative Services, don't get fooled by the XML syntax of the Service Component Descriptor:
<service>
<provide interface="com.example.FrobnicatorService"/>
</service>
The
provide element has an
interface attribute, but the attribute value can be any old class.
The same is true in Spring: There is no rule forcing you to inject Spring beans only via their interface. Any old class will do, even when working with automatic transaction proxies (just make sure that CGLIB is on your classpath).
So remember the KISS principle and kill some of the interfaces you don't really need!