I have a passion for talking to people, identifying problems, and writing software. When I'm doing my job correctly, software is easy to use, easy to understand, and easy to write... in that order. Michael is a DZone MVB and is not an employee of DZone and has posted 52 posts at DZone. You can read more from them at their website. View Full User Profile

Code to the Interface, Even if the Interface is a Class

04.26.2012
| 8821 views |
  • submit to reddit

After spending a considerable amount of time trying to figure out how to refactor some particularly hairly (hairy + gnarly) data access code, I thought I'd share some insight into a popular misconception about what coding to the interface actually means.

Let's say we're writing a data access layer and we have something called the UserDAO. a simple implementation might be something like:

public class User {
    public int id;
    public String name;
}
public class UserDao {
    public boolean save(User toBeSaved) {
    
    }
   
}

I'm going to dodge the issue of the user class not having getters and setters and thus not following the javabean spec and talk about the UserDao Interface. Yes, you heard me, the UserDao class effectively is an interface in this example. Sit down and just think about that for a minute, once you've done that, move to the next paragraph.

A great (GREAT) many java developers might not get to this paragraph because they'll immediately start reacting to the idea that the UserDao isn't a java interface, it's a java class. This is an implementation detail and I'm here to tell you that you have already started down a path of increased complexity. Why? because most java developers will, instead of just using the above two classes, add another layer of indirection.

public interface UserDao {
    public boolean save(User toBeSaved);
   
}
and change the UserDao to implement this class:
public class UserDaoImpl implements UserDao {
    public boolean save(User toBeSaved) {
    
    }
   
}

Which in my experience is of no value in a large percentage of use cases (let's call it 90% of the time). This is a mistake! I know that "best practices" from just about every source you'll find say this is a good idea, but I'm here to tell you that you are taking on debt and you should CAREFULLY weigh the cumulative cost of that debt. The biggest problem is that in non-trivial systems, this has adds unnecessary complexity to the design and makes things more difficult to decypher. There are other problems, but my biggest problem with this assumption is that not just the added complexity, but the knee jerk non-thought that goes into adding the complexity for no good reason. Imagine if you have 90 DAOs and 90 interfaces and every change to the interface requires a change in two places.

But Mike! people will say, what if my current implementation uses hibernate and I want to switch to ibatis? Fine, I'd answer, change the implementation of the save and get methods in your simple UserDao to use the other library. An example would be to use composition in the Dao to hook to the particular implementation you need (example use spring autowired beans).

public class UserDao {
    @Autowired
    private HibernateSession hibernateSession:
    public boolean save(User toBeSaved) {
        return hibernateSession.save(toBeSaved);
    }
   
}
and when we decide to use ibatis
public class UserDao {
    @Autowired
    private IbatisSession ibatisSession;
    public boolean save(User toBeSaved) {
        return ibatisSession.save(toBeSaved);
    }
}

I realize it's not really that simple (I don't know ibatis well enough, sorry), but my point is that the class in this example is GOOD ENOUGH as the interface. My rejection of the "automatically use a java interface" is because there are good reasons to USE an interface, but this example is NOT one of them.

So when is a good time to use an java interface? The time to use interfaces is when you have multiple things that need a shared interface (set of operations), but they don't necessarily have the same concrete class backing them. This design detail is java's way of handling multiple inheritance. In the context of most J2EE apps, DAOs are not a good use of the concept, a better example would be something like getting audit information for multiple entities:

public interface Auditable {
    public String getAuditString();
}
public class User implements Auditable {
    public int id;
    public String name;
    public getAuditString() {
        return "User " + id + " with name " + name;
    }
}

public class Account implements Auditable {
    public int id;
    public String accountNumber;
    public getAuditString() {
        return "Account " + id + " with account number " + accountNumber;
    }
}



public class AuditDao {
    public void audit(Auditable toBeAudited) {
        System.out.println("performing operation on:  " + toBeAudited.getAuditString());
    }
}
public class UserDao {
    @Autowired
    private HibernateSession hibernateSession:
    @Autowired
    private AuditDao auditor;
    public boolean save(User toBeSaved) {
        auditDao.audit(toBeSaved);
        return hibernateSession.save(toBeSaved);
    }
}


public class AccountDao {
    @Autowired
    private HibernateSession hibernateSession:
    @Autowired
    private AuditDao auditor;
    public boolean save(Account toBeSaved) {
        auditDao.audit(toBeSaved);
        return hibernateSession.save(toBeSaved);
    }
}

I realize there are better ways to implement this particular variation, but my point is that the auditable interface requires to implementation by completely different classes to happen at runtime. Hiding things behind interfaces should only be done if necessary and can provide realistic known value in the present or real future. Switching implementations can often be done in other ways when you spend time to think about your design. Java interfaces are for enabling multiple concrete classes to have the same interface, NOT necessarily for simply defining the interface of a concrete class. With good design, a class will hide it's inner details and the interface is just extra complexity.

Published at DZone with permission of Michael Mainguy, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mark Priest replied on Fri, 2012/04/27 - 12:04am

What about unit tests?  In our application, we frequently implement Daos by hard-coding certain behaviors in place of the true production implementation.  Ideally, you would stub out most application interfaces with a test impl if you are good about unit testing.  I would argue that the need for unit tests largely nullifies what you are saying about avoiding interfaces for convenience.  

In any case I don't see much extra work in implementing an interface with modern IDEs with templates and wizards for refactoring and code generation.

Andreas Schilling replied on Fri, 2012/04/27 - 2:19am

While you certainly have a point there on which I totally agree on, I think you chose a not very good example. The DAO-Layer for me is THE place where I use interfaces, as in my case it is generic and each DAO at first implements the very same interface. Then my services on top basically work with that interface in 99,9% of the time.

A better example IMHO would be places where you insert interfaces on suspect and later on you both realize that you still only have one implementation of that interface or that you have maybe 2 or 3 but all you actually wanted (and needed) to have is a simple base class with the shared functionality. We e.g. did that for a transport object that encapsulated complex query input data and the interface was just unnecessary "sugar". A simple base class would have been a wiser choice.

Marek Dec replied on Fri, 2012/04/27 - 3:10am

Programming to Interface is probably one of the most misunderstood principles in software development. See this stackoverflow question what does it mean to program to an interface?  and count the correct answers vs the wrong ones. The very correct answer appears somewhere down there, below many erronous answers based on the common misconception that 'Program to Interface' = 'define explicit interfaces'.

Back then in early 90s the very Gang of Four book states clearly that a class implicitly exposes its interface. Having an explicit interface that duplicates classes' methods buys you nothing in terms of decoupling. The implicit interface defined by the set of public methods are exactly as good as a java 'first-class-citizen' interface. Both define a type. The clients that use this type are coupled only to the methods' signatures. You can always change the underlying implementation as long as you don't modify the signature (i.e. the interface).

And as both java class and java interface declare a type and expose their interface both are equally good for implementing a mock implementation. If you write mocks by hand (does anybody still do that?) just extend the class to get an alternate implementation (given it is not final). That's what modern mocking frameworks do anyhow (and they are even capable of mocking final classes,see PowerMock, and also Mockito, Komarro)

Of course there are many good legitimate reasons to use interfaces (e.g. expose a limited set of methods, pure java proxies etc), however don't forget about a bit of healthy skepticism when following patterns.

 

Mikael Couzic replied on Fri, 2012/04/27 - 3:25am in response to: Mark Priest

When it comes to Unit Testing, you can automatically generate a stub with a mocking library without the need of an interface. When it comes to Integration Testing, it might be a bit trickier, depends on the technologies you rely on.

Mladen Girazovski replied on Fri, 2012/04/27 - 6:40am in response to: Mikael Couzic

Mocking a final Method for instance will need additional libs like PowerMock, but in an OSGi environment that simply won't work IME, not just "be a bit trickier".

Carlus Henry replied on Fri, 2012/04/27 - 7:01am

Michael,

 I 100% wholeheartedly agree with this position.  I have been a Java developer for the past 10 years, and I cannot tell you how many times I have been guilty of creating interfaces for classes that only have one implementation.  This of course was done in the name of "good design" practice.

Recently, I have switched over to hardly using interfaces at all.  Instead, my classes just depend on eachother outright - except for those cases where we do have multiple implementations of the same interface.  Overall, I have found this way of writing code to be much more simple due to the facts that you have mentioned as well as a reduction in the amount of code that we have to support.

Thanks for putting into writing feelings that I share and support. 

Jose Maria Arranz replied on Fri, 2012/04/27 - 8:56am in response to: Mark Priest

Regarding tests as already pointed out before, you can use three generic base classes for your DAOs instead of interfaces:

1) One stupid base class mainly abstract, maybe with some very generic code. Code calling your DAOs will use this base class. E.g. GenericDAO

2) Another like RDMBSDAO extends GenericDAO with real generic but useful code to be used by inherited classes.

3) Another like TestDAO extends GenericDAO maybe with some generic code for testing (mocking). Inherit your concrete test-DAOs from this class.

Although you remove test code, the classes GenericDAO and RDMBSDAO still keep sense and do something useful.

And don't forget generics to avoid casting :)

Said this, interfaces still have sense if you need to call specific methods for querying specific entities (GenericDAO is too generic).

In summary, my advice is, try first with abstract classes, avoid using inherited classes in your code, this allows testing and switching implementations with almost no impact, if this is not enough then add interfaces.

Sylvain Leroy replied on Sat, 2012/05/05 - 4:38pm

I rather agree with you Michael,

 Programming with interfaces is rather valuable in conditions like

  • mock testing,
  • api desig
  • programming and retro-compatibility
  • layer separation
  • reducing the regression perimeter during migrations and huge refactorings
  • plugin api development

However it is becoming fastly cumbersome inside an API or a SDK where this class is only used in one context and simple.

Furthermore, I discover that Eclipse software does miracle to destroy our carefuly designed api by automatically refactoring my interfaces and breaking plugin contracts.

www.techdebt.org

 

 

Haris Michopoulos replied on Sun, 2012/05/06 - 12:56pm

I totally agree with you. Furthermore, we should consider even the number of classes.

And the DAOs example is ideal.

We create tens of classes with very similar functionality, most of which can be covered by a single DAO class with few methods.

Yusuf Jakoet replied on Mon, 2012/05/14 - 7:54pm

Your example of using DAO's is a bad one as with generics, the implementation of the DAO pattern makes it a prime candidate for using interfaces.  In your example, an interface isn't required as you're effectively duplicating the same behaviour in each class, the only difference being type.

Think about this:

List<String> names = new ArrayList<String> ();

Dao<User> userDao = new JDBCDao<User> ();

In this case, why would you not use an interface?

In your example, your DAO's would effectively have a common interface, with only data types that differ.  Once you see that, then you'll want to change the design of your DAO's completely and your argument against interfaces (whilst valid), will be less relevant to you.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.