Why always have single implementation interfaces in service and dao layers?

I've worked/seen a few spring-hibernate web application projects having as many interfaces as there are actual service and dao classes.

I always thought that these two as the main reasons for having these single implementation interfaces:

  • Spring can wire actual implementation as dependencies in a given class (loose coupling)

    public class Person { 
        @Autowired 
        private Address address;
    
        @Autowired 
        private AccountDetail accountDetail;
    
        public Person(Address address, AccountDetail accountDetail) 
        { // constructor
    
  • While unit testing, I can create mock classes and test a class in isolation.

    Address mockedAddress = mock(Address);
    AccountDetail mockedAccountDetail = mock(AccountDetail);
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows
    
  • But, of late, I realized that:

    Spring can wire concrete implementation classes as dependencies:

    public class Person { 
    
    @Autowired 
    private AddressImpl address;
    
    @Autowired 
    private AccountDetailImpl accountDetail;
    
    public Person(AddressImpl address, AccountDetailImpl accountDetail) { 
    // constructor
    

    Mock frameworks like EasyMock can mock concrete classes as well

    AddressImpl mockedAddress = mock(AddressImpl);
    AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl);
    Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); 
    // unit test follows
    

    Also, as per this discussion, I think the summary is that within a single app, interfaces are mostly overused probably out of convention or habit. They generally make best sense in cases where we are interfacing with another application for example slf4j used by many apps around the world. Within a single app, a class is almost as much an abstraction as an interface is.

    So, my question is why do we still need Interfaces and then have single implementations like *ServiceImpl and *DaoImpl classes and unnecessarily increase our code base size. Is there some issue in mocking concrete classes that I'm not aware of.

    Whenever I've discussed this with my team-mates, only answer I get is that implementing service and dao classes based on interfaces is THE DESIGN everybody follows - they mention about spring best practices, OOP, DDD etc. But I still don't get a pragmatic reason behind having so many interfaces within an isolated application.


    There are more advantages to interfaces - As in proxying . If your class implements an interface , JDK dynamic proxies will be used by default for AOP . If you use the implementations directly, you'll be forced to use CGLIB proxies by making proxy-target-class=true . These require byte code manipulation unlike JDK proxies .

    read here for more on this .

    Read another discussion at what reasons are there to use interfaces (Java EE or Spring and JPA) for more info .


    It's a very controversial subject. In brief, there's none—at least for you, the developer.

    In EJB2 world, the Home and Remote interfaces were a must, and were exactly for a reason @AravindA mentions: proxies. Security, remoting, pooling, etc. all could be wrapped in a proxy, and provide the services requested strictly within standard library (as in DynamicProxy ).

    Now that we have javaassist and cglib , Spring (Hibernate, EJB3 if you prefer) are perfectly capable of instrumenting your classes as framework developer likes. Problem is, what they do is a very annoying thing: they usually request you to add a no-parameter constructor.—Wait, I had parameters here?—Nevermind, just add the constructor.

    So interfaces are here to maintain your sanity. Still, it's strange, a no-argument constructor for a class with proper constructor is not something that makes a sense to me, right? Turns out (I should've read the spec, I know) that Spring creates a functional equivalent of an interface out of your class: an instance with no (or ignored) state and all the methods overridden. So you have a "real" instance, and a "fake interface" one, and what fake interface does is, it serves all the security/transactional/remoting magic for you. Nice, but hard to understand, and looks like a bug if you haven't taken it apart.

    Moreover, if you happen to implement an interface in your class, (at least some versions of) Spring suddenly decides you were going to proxy this interface only, and the application just doesn't work for no apparent reason.

    Thus, so far the reason is, safety and sanity. There are reasons why it is a good practice—but from your post, I see you already read all of those. The most important reason I can see today is the WTH/minute metric, especially if we're talking about newcomers to your project.

    链接地址: http://www.djcxy.com/p/87894.html

    上一篇: JpaRepository中的SERVICE层

    下一篇: 为什么在服务和dao层中总是有单一的实现接口?