Program to an interface not an Interface

For the longest time I have thought I was crazy, because I just didn’t see the benefit of programming to an Interface. I agreed it was good from a design perspective, but as an implementation I saw no need to add the extra code for what amounted to zero benefit. I have finally come to the conclusion that a good chunk of people have absolutely lost their mind. I base that conclusion on the fact that I have found smart people that agree with me, to counter the smart people that lost their mind.

What am I talking about? I will cut straight to the point, when the GoF suggested programming to an interface not an implementation in their classic book, I don’t think they meant a Java Interface. Mostly because the book was based on C++ and Java Interfaces weren’t around, but also because I think they are smarter than that.

Like so many things in the Java community, I think they took a really great idea and twisted it until it no longer made sense. I don’t think they do this on purpose, I believe they are just gluttons for theories. But, before I get to far into this rant, let me substantiate this claim with a few points of interest.

  • Almost all languages at the time of the GoF publication did not have the notion of an interface as a first class citizen.
  • The examples in the book were written in C++ which did not have the notion of an interface, although you can fake it.
  • Patterns are supposed to be reusable bits of object oriented goodness, and since all object oriented languages don’t include interfaces as first class citizens it might not be essential to use these ideas.

Now let me switch into argument mode, I agree with the notion of programming to an interface. I admit that doesn’t sound like a very good argument, but hear me out. I will address each of the popular arguments individually, so what are they?

If you don’t use an Interface you are programming to the implementation not the interface.

So the point here is that you should be loosely coupling your classes in your application. When designing your systems you should always think about the interface (coupling) between your components and make sure they make sense. I firmly believe the best way to make a maintainable system is to create loose coupling and high cohesion as a wise man once taught me. But this can and is done in many languages, and at many shops without the need for the Java Interface.

So what am I saying? I am saying if I showed you the following code:


public class BankDelegate {
   public void debit(Account account, Amount amount) {
      account.debit(amount);
   }
}

you would have no idea if account was an Interface, Abstract Class, or Concrete Class. And furthermore, I would suggest that it doesn’t matter. Let’s say my bank only has a single account type. This would work great. Now what happens when I need to add a second account type? I can either create a base class, that both my accounts extend from, or I can create an Interface. Either solution will work, and I don’t need to change the code in my delegate. Which means my interface has remained the same.

That is what it means to program to an interface. Because if I had originally wrote the BankDelegate class like this:


public class BankDelegate {
   public void debit(CheckingAccount account, Amount amount) {
      account.debit(amount);
   }
}

Then my interface is only good for classes that are of type CheckingAccount. So let’s apply the same logic as before. I could write this as an Interface, Abstract Class, or Concrete Class and you would have no idea based on the above code. But of course, had I written it as an Interface it would be loosely coupled, and therefore I would be able to change it extremely easy at a later time…Oh wait, errrrr…It doesn’t make sense for a SavingsAccount to extend Checking account. I need to add a new base class or interface of Account and extend that. It will take the same amount of work to change this to accept a SavingsAccount regardless of what notation I used to create the CheckingAccount type.

Because of that I would argue that programming to an interface is more about thinking about the names of your classes and methods than using a special notation to declare them.

Why would you tie down your domain with unnecessary dependencies?

This is the argument that if I don’t create an interface, I will be importing unnecessary third party dependencies into my domain. The example I have seen suggests if you are creating a store, and you need to keep track of sales, you should create a SalesLedger interface. That way you can create a HibernateLedger that implements the SalesLedger, so as to not couple the Hibernate libraries to your domain. I agree with the idea of not coupling your domain with hibernate, but I don’t see how adding an Interface solves this. Even if I make the Interface I could make it rely on hibernate functionality, especially if it is the first and only implementation I do. Futhermore, the argument seems to suggest that I would have created the class HibernateLedger in place of SalesLedger if I had not created the Interface. That is probably true from the implementation standpoint, but form the interface standpoint, the methods would be identical to SalesLedger, the Interface. Am I missing something?

More importantly however, it is not unnecessary from a runtime perspective, which is essentially the only time you are ‘importing the dependency’ because without the Hibernate classes your code won’t work, no matter how many Interfaces you placed in between.

How else can you change the implementation in the future?

I am sorry, but this is ridiculous? Let’s break this down into what that really means.
1. If you mean changing it at runtime…that has more to do with the strategy pattern and your runtime environment, that a Java Interface. If you needed to change an implementation at runtime, you simply extend the original class, change the behavior you need, and inject your new object.
2. If you mean changing it for a future build…just re-write the code. Will you need the old code? Do you like keeping an archive of all your classes? If you need to change your SalesLedger to use a web service, instead of hibernate, go for it. You wouldn’t be using both at the same time.

So you ask, what if I need the old code in the future? I would say, isn’t that what version control is for.

What if we need to change the parameters in the future?

This is the one that I find most disheartening. The idea here is doing something like this


public void myMethod(IMyParameterInterface request) {
    ...
}

instead of this


public void myMethod(String param1, Integer param2) {
    ...
}

Talk about working around language features. What if you need to change the parameters in the future you ask? I don’t know change the parameters. I know, the response is, well then your interface has changed, and you need to go update everyone consuming that interface. Yeah, well guess what you just added a new parameter, that they probably need to send, and if they don’t, you can just overload the method and pass a null, which you would have to check for in your Interface based system as well.

So there you have it…

I recognize that Java Interfaces are essential to the language, because Java is a static typed language, and doesn’t allow multiple inheritance, Interfaces are the only way to create libraries like the collections API. I think it is unfortunate that the word ‘interface’ has been overloaded so much, that in this case it was taken literally becase and Interface type existed, instead of just treating it in the more generic term, of interface between two components or systems.

In conclusion, I hope I have enlightened, and annoyed a few people with this article. And maybe I don’t know what I am talking about, but just incase I haven’t been able to convince you, read this interview with Eric Gamma, I think you will find it enlightening.

This entry was posted in programming, rant, social, theory and tagged , , , , , , . Bookmark the permalink.

10 Responses to Program to an interface not an Interface

  1. Michael Sica says:

    I agree, even in scenarios where you’re implementing an interface in your class (like the threading stuff in java – what is it, runnable?) the only thing you’re getting from an Interface is the compiler saying, “hey, you did this wrong”… Like you weren’t going to ever run the code until it’s in a production/mission critical/life threatening situation?

    If I’ve got an API doc – I’m good.

  2. Great post. I feel like I don’t have much to add to this discussion right now, so I’ll leave it at good job.

  3. Theo Briscoe says:

    I concur, the idea of creating all the interfaces up front (before they are needed) does not make sense. All the modern IDE can generate interfaces later in the development process when they are needed.

  4. Russ says:

    I think its probably part of the learning experience. Everyone goes through a collection of practices until they learn what’s useless and what’s not. The mix up in nomenclature from the GoF book is likely the cause… but the end result of making an interface for everything in your system isn’t entirely bad. Its a tedious way of learning how to think about the (lowercase) interface (as opposed to the uppercase one). Once you learn that you can make better concrete classes and only extract interfaces when you need them. The debate will continue, though, because there’s always someone who doesn’t know any better.

  5. Daniel Roop says:

    @Russ

    Very good point, I agree you don’t lose much by creating the interface, but it does clutter up your packages, and increase the files you need to maintain in your software. And we all know the more lines of code, the more bugs in the code ;-).

    Regardless, that is a good point, I just wish more seasoned developers would speak out, so that the new developers don’t get stuck believing the interface advocates are the only seasoned train of thought.

  6. Pingback: Fat Agnus » Program to an interface, not an implementation

  7. Justin Holzer says:

    IMO, the whole point of programming against interfaces is to be able to define expected behavior without having to go in to details about how the system will be implemented to carry out the behavior. Sure, you can inherit from a concrete or abstract class, but at that point, you are combining the definition of the expected behavior (i.e. method signatures), with the actual implementation of that behavior (optional for an abstract class of course).

    Also, inheriting from a base/super class is not a substitute for a Java/C# interface, as you cannot force the sub-class to override non abstract methods. Sure, you could build an abstract class and declare all methods abstract, but at that point, why not just use an interface? Definition of expected behavior and implementation of that behavior should be kept separate, if possible. If you have the Interface (in the Java/C# sense of the word), why not then take advantage of it?

  8. Jason says:

    Another reason why you might not want to use an interface is if you need the object to have a certain method available but you don’t want to make that method public. You can’t do that with an interface. An abstract class is the best alternative but IMO it makes just as much sense to make a concrete class. A concrete class can still be extended and overridden and in a worst case scenario that concrete class can be turned into an abstract class without impacting the client of that class as long as the concrete class cannot be constructed outside of your control. What I have proposed is the use of concrete classes with package, or lower, access constructors. This gives you all the benefits of programming to an “interface” without unnecessary code waste.

    • stakx says:

      Another reason why you might not want to use an interface is if you need the object to have a certain method available but you don’t want to make that method public. You can’t do that with an interface.

      Of course not. The whole point of interfaces is to encourage you to think in terms of contracts, not implementations. If a method isn’t public, then it can’t be part of a contract, and you’re therefore not creating an interface type (no matter whether it’s encoded as a class or as an interface); you’re creating an implementation.

      This is one example of how Java’s and other languages’ interface syntax makes it more difficult to accidentally mix up public contract with implementation concerns: by only allowing public members.

  9. Michael says:

    One thing you get from programming to an interface is making it easier to do unit tests. It means you can easily replace bits which are hard to deal with in the test (like file system access) with mock parts. And at least in theory, using unit tests to debug your code can save you quite a bit of time, especially if your code is complex enough that a build and run test iteration of the full thing is slow.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>