Using Interfaces in Java Applications

Myths about interfaces

For every class, you should create an interface.
Interfaces always save you more time later even though you think you might not need them.
An application is not testable unless it has lots of interfaces.
Interfaces are necessary for testing only.
Good naming means using “I” for the interface prefix and “Impl” for the class suffix.
If you use interfaces, you won’t need to refactor anything later.

Introduction

in·ter·face
A tool and concept that refers to a point of interaction between components, which forms a contract between the class and the outside world.

There has certainly been a significant amount of discussion and debate on just how, when, where and why to use interfaces. Anyone would agree that interfaces are among the most important building blocks of software applications. However, they are also among the most misused and misunderstood parts of software today. Perhaps that’s due to one popular misconception that interfaces are a “must” for testing, and another misconception that interfaces will always make applications more flexible and less prone to future refactoring. The world of software would be a great place if only there were a common consensus that there will always be an influx of new information, making change inevitable. Continuous refactoring should be embraced, rather than feared.

But there should be a method to the madness. Before you create an interface, you should think hard about why you need it, and whether you need it at all. We all would like to predict the future and know whether things will change, how things will change, and when things will change, but the truth is, we don’t. That’s why you should start small. Gather as much information as you can, but only program for what is needed at the time. Keep things simple. Let your application evolve in a natural way, and refactor it as you go.

At the end of the day, one should realize that interfaces are contracts. Now take a moment and think about some of the contracts you have signed in your life. You might have a bank mortgage contract, a cell phone contract, and a health insurance contract. Now think about how these companies began their businesses several decades ago, and designed their contracts. When these businesses were startups as every business is, the first agreements must have been casual. “Hey Joe, I will lend you some cash so you can buy your house but you have to pay me back in 5 years, and give me 7% interest. If you can’t pay it back then I get to keep your house.” It must have started out like that, but over time as business needs evolved, the contract changed and new rules were added. Today, the contract might be 20 pages long. Did the contract start out that way? No. Could anyone have anticipated what all these rules would be in the beginning? No way. Contracts evolve over time, even though it is very costly (imagine when your bank or cell phone provider changes a rule in the contract. All the customers must be notified, and many might object to the new rule!)

So we see, since we can’t always predict the future, interfaces aren’t ALWAYS the answer to “saving time when things change later”. A good application has good architecture and a clear separation of roles, good interfaces, is simple to understand, and easy to maintain. The only answer to creating a good application is investing time in significant design consideration and continuous refactoring. My advice about interfaces…. create them only where it’s appropriate to do so. Don’t create interfaces for no reason. Be aware of the pitfalls. Continuous refactoring is often inevitable, and simple code is easier to refactor. And once and for all, do away with the darned “I” interface prefixes and “Impl” class suffixes!

Reasons to use interfaces

- More flexibility, ease of refactoring, loose coupling… when you depend on abstractions not details
- Code reuse – other classes can implement more than one interface but can’t extend more than one class
- Easier to integrate with other systems
- Mocking is cleaner with interfaces (though possible with concrete classes)
- Creates an implementation contract
- Enforces code organization and conformity

Interface pitfalls

- Can’t step into the code as easily (code browsing nightmare)
- Can’t “evolve the contract” i.e. change the interface without breaking the implementations
- Additional class to maintain

When to use interfaces

Before you create an interface, you might want to ask yourself the following questions:

1. Will I have more than one implementations of this class and need to swap them around later?
2. Will I implement other classes that will have similar methods?
3. Is this class for data methods (getters and setter methods) or does the class perform something (service methods)?

As I have already mentioned several times, interfaces are of great use when you need to swap around implementations of classes. As we saw in the previous article about dependency injection, the CopyService class suddenly became more flexible when it depended on the interfaces Reader and Writer, instead of depending on concrete implementations Keyboard and Printer. Once the interface Writer was in place, it was possible to swap the implementation PrinterWriter with PdfWriter without restarting the whole system.

Here’s another time when it makes sense to use an interface. You might find yourself writing many classes that have similar methods. For example, you might have a series of products that need to be added to the database and find yourself writing many classes with methods to add, delete, and find each type of product. An interface will come in handy to enforce some code conformity among all the classes you are implementing. (see example below)

It is a good idea to understand the relationships between the different objects you are implementing. Here are a few important ones:

is-a (inheritance, no interface)

public class Product { }
 
public class Camera extends Product { }

Here, Camera is a Product. So, in this case we have simple inheritance and there is no need for an interface.

has-a (attributes, no interface)

public class Camera extends Product { 
    private String brand;
    private double lenswidth;
    private double weight;
    public void setBrand(String brand) {
        this.brand = brand; 
    }
        ...
}

Here, Camera has a brand, it has a lenswidth and it has a weight. These are all data attributes, and there is no need for an interface.

performs (use an interface!)

public interface ProductManager {
   public void add(Product product);
   public void delete(String productid);
   public void findById(String productid);
} 
 
public class CameraManager implements ProductManager {
   public void add(Camera camera){
     //TODO implement this method
   }
     ....
}

Here we have a class that performs some action, so it makes sense to use an interface. Why? A couple reasons. First, you might have many more products in the future like Computer, Stereo, and Phone, and they will all have to have their own implementations of adding, deleting, and searching. If all product types need their own Manager (in some cases it’s possible to avoid this and make one Manager for all) then it is best to create an interface to make some conformity among the methods. And, this gives us flexibility in the future if we should need to change our implementations someday, if we would like to access our data in a different way, then we can just create a different CameraManager. Now we can use the ProductManager transparently in other classes and we can pass a Camera or a Computer or whatever we want, as long as it is an extension of Product.

There is another reason that many people seem to add lots of interfaces to their code. Testing! I will cover testing in the next section. For now, all I will say now is that in order to understand whether or not to introduce interfaces to your application just for testing purposes, you must understand quite a bit about testing. Testing involves mocking of certain classes/interfaces, and interfaces are in many cases easier to deal with because you can create a mock implementation of the interface and swap it easily. If you need to mock a concrete class then it is also possible with mocking tools like mockito. It’s just important to not design your whole application architecture around the idea that you will need interfaces just for testing. You should add interfaces if they add value to your application.

Naming interfaces

When I was browsing around the internet in search of a good naming convention for interfaces and class implementations, I saw a whole lot of ranting. Some of it was pretty entertaining! Here is one post from stackoverflow that I enjoyed reading and thought was quite insightful:

Name your Interface what it is. Truck. Not ITruck because it isn’t an ITruck it is a Truck. An Interface in Java is a Type. Then you have DumpTruck, TransferTruck, WreckerTruck, CementTruck, etc. When you are using the Interface Truck in place of a sub-class you just cast it to Truck. As in List. Putting I in front is just crappy hungarian style notation tautology that adds nothing but more stuff to type to your code.

All modern Java IDEs mark Interfaces and Implementations and what not without this silly notation. Don’t call it TruckClass that is tautology just as bad as the IInterface tautology.

If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions is AbstractTruck. Since only the sub-classes will every see this and you should never cast to an Abstract class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than AbstractTruck and use BaseTruck instead. But since Abstract classes should never be part of any public facing interface it is an acceptable exception to the rule.

And the Impl suffix is just more noise as well. More tautology. Anything that isn’t an interface is an implementation, even abstract classes which are partial implementations. Are you going to put that silly Impl suffix on every name of every Class?

The Interface is a contract on what the public methods and properties have to support, it is also Type information as well. Everything that implements Truck is a Type of Truck.

Look to the Java standard library itself. Do you see IList, ArrayListImpl, LinkedListImpl? No you see. List and ArrayList and LinkedList. Here is a nice article about this exact question. Any of these silly prefix/suffix naming conventions all violate the DRY principal as well.

Also if you find yourself adding DTO, JDO, BEAN or other silly repetitive suffixes to objects then they probably belong in a package instead of all those suffixes. Properly packaged namespaces are self documenting and reduce all the useless redundant information in these really poorly conceived proprietary naming schemes that most places don’t even adhere to in a consistent manner. If all you can come up with to make your Class name unique is suffixing it with Impl, then you need to rethink having an Interface at all. So when you have an situation where you have an Interface and a single Implementation that is not uniquely specialized from the Interface you probably don’t need the Interface.

I would have to agree what this guy is saying, and have been frustrated by the overuse of the “Impl” suffix and “I” prefix. It makes the code slightly unreadable. I think this notation is good for writing articles and examples but too many developers went ahead and put it directly into the code, and some even follow the silly pattern of creating an interface for each class, for no reason at all.

Maybe I didn’t emphasize this point enough yet. For code to be readable, it is essential that classes, interfaces, methods, and attributes are named appropriately! Otherwise, code can be misleading. There is however, sometimes the questionable situation where you have an interface with only one implementation. You might be planning to have more than one implementation in the future but for now there is only one. What do you do? Well, you have two choices. Instead of naming the interface and implementation ITruck and Truck, or Truck and TruckImpl, you could call them Truck and DefaultTruck. That makes most logical sense in my opinion. The other option would be to not create an interface at all, and if you manage the dependencies correctly, then refactoring should be a breeze if you need to create an interface later.

Refactoring

Sometimes when you are not sure whether to add an interface or not, it is easier to just wait until the classes evolve and you have more information about the requirements. Often it is only clear what the method signatures of a class will be only after the classes are developed. It is also becomes clear later which classes are similar and can be grouped together to implement the same interface. If you create interfaces too early in the development process, it could be painful when you go to change the interface because you will have to change all the class implementations as well. That’s not fun! So, if you are unsure about creating an interface, you can wait until later and won’t have a mess refactoring if you inject the dependency properly. You can inject the class dependency with Spring, so classes depending on your concrete class won’t even know it is a class implementation. For example, if you have a class called TruckDao and are not sure whether you will need an interface or not since for now there is only one implementation, then you can just leave it as follows:

public class TruckDao {
   public Truck findTruckById(String id){ 
     ....
   }
}
 
public class TruckService {
    private TruckDao truckDao;
    public void setTruckDao(TruckDao truckDao){
       this.truckDao = truckDao;
    }
    public Truck findTruck(String id) {
        return truckDao.findTruckById(id);
    }
}

See, TruckService has a dependency on the class TruckDao. But, TruckService doesn’t even know if TruckDao is a class or an interface! We have configured it with spring like this:

<bean id="truckDao" class="com.monstertrucks.TruckDao">

Say tomorrow we want to add an interface. We refactor TruckDao to be an interface, because we have two implementations, HibernateTruckDao and IBatisTruckDao. All we would need to do is convert TruckDao to TruckHibernateDao for example, and change TruckDao to be an interface. Then update the xml:

//this class used to be called TruckDao, now it's refactored to HibernateTruckDao
public class HibernateTruckDao implements TruckDao {
   public Truck findTruckById(String id){ 
     ....
   }
}
//now TruckDao is an interface
public interface TruckDao {
   public Truck findTruckById(String id);
}
//no changes to this class!!!
public class TruckService {
 ...
}
<bean id="truckDao" class="com.monstertrucks.HibernateTruckDao">

This is might seem trivial, but if we had 200 TruckDao dependencies and had not managed the dependencies correctly, then refactoring would be much more difficult!

0 Comments

Post a Comment

(required):