views:

343

answers:

5

I understand the principles of Coding to Interfaces - to decouple the implementation from the interface, and to allow implementations of the interface to be swapped in and out.

Should I code to interfaces for every class I write or is that overkill? I don't want to double the number of source files in a project unless it's really worth it.

What factors can I use to decide whether to code by interface or not?

+6  A: 

No, every class should not have an interface. It's overkill squared.

You use an interface when you need to abstract what's done from how it's done, and you're certain that the implementation can change.

Have a look at the java.util Collections API for a good example. The List interface is a nice abstraction for the general idea of a List, but you can see that there are many ways to implement it: ArrayList, LinkedList, etc.

UPDATE: So what about that case where you design a concrete class, decide after you have clients that an interface is needed, and then you break your clients by adding an interface? Yup, that's what happens. How can you know what you don't know? No software or methodology can fix that.

The good news for you is that extracting an interface from a concrete class is an easy refactoring to do for both you and your clients. IDEs handle that kind of thing routinely. You and your clients should take advantage of them.

I'd say that layers, like services and persistence, should always have interfaces. Anything that can be proxied should have an interface. If you're doing Spring AOP, anything that you want to decorate with an aspect should have an interface.

Model or value objects, like Person or Address or Phone, should not have an interface. An immutable value object should not have an interface.

The rest fall into gray areas. Use your best judgement.

duffymo
But what if you don't know you are goign to need the abstraction? E.G. You code a class without an interface, your clients depend on the class, you then need another implementation but cannot extract an interface without breaking binary compatability.
Tarski
^ this. Also, is it really that hard to just create an interface and have a class implement it? Does it really take much more time to just do it?
GreenieMeanie
+8  A: 

I use it when at least one of the following is true:

1) I want to decouple unrelated modules/classes from each other, and I want it to be reflected by the java package dependencies.

2) When decoupling is important in terms of build dependencies

3) When the implementation may change through configuration or dynamically at runtime (usually due to some design pattern)

4) When I want a class to be testable, I make its "link points" to external resources interfaces, so that I can use mock implementations.

5) Less common: When I want to have an option to restrict the access to some class. In this case my method returns an interface instead of the actual class, so the caller knows that I don't expect him to do other operations on the returned value.

Eyal Schneider
+1 for testability and access restriction
Dan Vinton
+2  A: 

Long story short, no. You are the creator of the application, so you have a decent idea of what could change. Some of the design pattern books go a little crazy on it in my opinion since they seem to always push designing to interfaces and not implementation no matter what. Sometimes, it is just overkill. For my latest application (small size), I have a database interface because I think there is a chance I may later port it to the web and switch to MySQL. Of course in reality, it would be easy to create a database interface down the road from my existing class and just add "implements myDbInterface" later with a couple of small changes. This works because I am the only developer though. On a larger team, or different type of product, it may be a different answer. Just use your best judgement (after reading all the good SO answers of course).

Awaken
+11  A: 

In general I agree with the other answers: use an interface when you know or anticipate change and/or different implementation, or go for testability.

But it's not always easy to know in advance what may change in the future, especially if you are not so experienced. I think the solution for that problem is refactoring: keep it simple (= no interface) as long as it is not needed. When the need arises simply do an "Introduce/Extract interface" refactoring (supported by almost all decent IDEs).

When you do it extract only those methods that are actually needed by the callers. Don't be afraid to extract more then one separate interfaces (if not all of the extracted methods are really coherent).

One driver of the refactoring might be the testing: if you can't easily test something with classes only consider introducing one/some interface(s). This will also allow you to use mocking which may greatly simplify testing in many cases.

Edit: based on Tarski's comment I've realized one more important scenario/adjustment to the previous statements:
If you provide an external API (for other [sub]projects, or really release it "to the wild") then using interfaces in the API (except for simple value classes) is almost always a good idea.
It will allow you to change the impl if you like without disturbing the client code. You will have a problem only if you also have to change the interface. Not breaking compatibility will be very tricky (if not impossible).

Sandor Murakozi
great answer. I've encountered exactly this - I had a class used by multiple client projects and now need an interface to offer an alternative implementation - i could use overriding but it's not as clean. The problem is that I then need to recompile all the existing clients to use the interface. As you put it, I didn't know I needed the interface when I started
Tarski
You are right with the recompilation, you have to do it after the refactoring, but only once. After that implementation is nicely decoupled, so you are free to change it/add new ones without the need for recompilation.
Sandor Murakozi
+1  A: 

I like to think of that one uses interfaces when pluggability and the potential for different behaviour is important. Services are the perfect fit. One might want a default implementation, but faking(mocking) etc is another. This obviously means there should be an intf as there will always be at least 2 forms.

Value types on the other hand should be final classes. They should never be extended. Value types include something like Suburb, MimeType. If there are variations of these use composition. As a goal i try and put little behaviour if any in my value types. Validating the simple type it wraps etc is probably the most complex thing that it does. Eg A Color class which takes r/g/b should validate that each component is between 0 and 255 and thats it.

mP