Developer note: thinking about Java interfaces
Last week I gave another training. The group consisted of mostly fresh developers. One of the characteristics of such developers, is misunderstanding the Interface concept. When I say "interface" I'm referring to Java interfaces (interfaces were not part of the original OOP concept). In my opinion, understanding and using interfaces correctly is a positive sign of a mature and experienced enterprise developer.
Interfaces are the path which leads to the decoupling heaven. A developer working on his/her own or in a very small team cannot fully comprehend the importance of true decoupling of components. For me, I think it was COM which made the difference. COM, Microsoft's Component Object Model, defines a platform and a protocol for connecting binary components. Binding binary components means that the components are compiled to a binary form, hence, can be written in virtually any language. The icon representing an object (or component) in COM was a box with "handles" which represent the interface. An object can only be handled by the interface.
Obviously, this is not the case in Java. Java allows the tight coupling of objects. This leaves the responsibility to the developer.
Three thumb rules to achieve implementation independence:
- Return interfaces from your methods - do not return an actual implementation. This is especially important when dealing with public methods.
- When casting - cast to an interface rather than an implementation.
- All public methods should be defined in an interface. All other "implementation" methods should be kept private or protected.
This can bring you to the decoupling utopia... but it can also drive you crazy. Because:
- You will need to write and manage more code.
- Program structure becomes more complex.
- It's difficult to trace the program execution path when statically browsing the code.
The last point is a tough one. Modern IDEs can easily show you a "Call Hierarchy" view or simply jump to the method body. However, when working with interfaces this feature is disabled, since the execution refers to the interface and not the implementation. Here's an example of a Call Hierarchy view from Eclipse:
The solution is probably in a middle way. The developer needs to decide where it is necessary to decouple and where this is just a waste of time. It is difficult to give a well defined set of rules for the decision, hence, different people in the same team may come to different conclusions.
Final note: if the tools were good enough to work with interfaces intuitively, would you be using them to their full extent? I know I would.


Hi,
I love the concept of interfaces in Java. It is a really clean way to uncouple 'specification' from 'implementation'. It's good to know when to use interfaces, but it's however also good to know when *not* to use them - or rather when to ponder whether using an interface is indeed a smart choice.
There are sometimes some additional constraints that might come into play - so I'd suggest some additional thumb rules:
* If you're going to transmit the objects returned over the wire (RMI) you could consider using concrete classes instead: the serial form is defined on the concrete class, not on the interface. Maybe you will determine that using an interface is still the right choice in this case, but you will also need to define a (set of) concrete class(es) implementing it and make them part of the public API.
* If you're developing a library, or an application that can be extended with user code, then once you've defined an interface, it's basically frozen: you will not be able to add anything to it in the next version, because you would break any class implementing it. There's no way to prevent any third-party/user code to implement the interfaces you've defined, so there's no way to know what will break if you modify it. Instead you will need to introduce a new interface that extends the previous one. After a while you might run out of meaningful names for these new interfaces. So if you suspect that you might have to add methods to the interface in the future (next version of the API) you might want to ponder whether to use an abstract class instead.
Using and defining interfaces is good - but I prefer when it's the result of a thoughtful design choice rather than the simple application of a global rule. As your conclusion says: "it is difficult to give a well defined set of rules for the decision"...
Cheers,
-- daniel
Posted by: daniel | Nov 26, 2007 at 14:04
Hello,
regarding handling interfaces intuitively from Eclipse, I can recommend the Implementors Plugin. From their site:
The Implementors plugins add the possibility to jump to the implementation of of an interface. Alternatively, you can jump to the interface of an implementation.
Basically you ALT + F3 a method on an object declared through an interface, and it brings you to the implementation (if there's only one), or gives you a list of implementations. This making navigating a bit less cumbersome when you are using lots of interfaces.
Posted by: Alex | Nov 26, 2007 at 14:12
Also, using an interface approach allows you to write better unit tests. I use the easy mock to plug-in the interfaces.
Posted by: doylecentral | Nov 26, 2007 at 14:46
Clearly this is not a "well defined set of rules", but taking code and thinking of it within a new context (e.g. a unit test) makes the more obvious design choices apparent.
In my experience, interfaces seem to naturally bubble to the surface as I write unit tests ...
Posted by: Tom Lee | Nov 26, 2007 at 17:57
Guys, thanks for great comments. Personally, I admit I'm not a big fan of TDD, but mocking is a great plus for interfaces. I'm not sure that this should be the strong motivation for your final design, but it's a consideration none the less.
@Daniel, indeed, an interface is a commitment which is hard to break. I'm now developing in Eclipse and there are many examples of Interface and then Interface2, Interface3, etc. That's what happens when you're not that creative.
There's a mitigation for that. You may define an interface and a base-class. Use the interface for interacting with the class and the base for implementing parts. It's not a perfect solution, but it will allow you to add methods without breaking backward compatibility. Of course, it also introduce a strong limitation: you're using the one inheritance Java provides (and, by all means, I think one is enough, but that's a topic for another post :-).
Posted by: Zviki Cohen | Nov 26, 2007 at 18:24
I agree with all you guys on the benefits of interfaces in the technical terms, like not binding to the implementation etc. But I think you are missing one, important pointe in the "when to use interfaces" debate.
Interfaces can be used to express a "role" in your domain model. Do you guys do real domain modelling? Cause then you will meet situations where something is not a class as such, but a way a class can act. It has a role. This role should be expressed in an interface. A class can have more than one role. An example is java.lang.Comparable.
Of course, this is not a role-or-nothing, thing. We can still do stuff like a "FooService" interface for a "FooServiceImpl" class, but, this is "just" to get the nice, technical decoupling you mention.
I just thaught that was important too :-)
BTW: IntelliJ IDEA can, and has always been able to, navigate directly to the implementation. Without plugins or anything. Shit, hope I didn't start a flame war there ;)
Posted by: Per Olesen | Nov 26, 2007 at 23:05
I agree that this is a hard one to get through to the junior developers.
Most start off with the attitude of "so what" and think they are a waste of time. This is made more difficult by some of the bad design decisions in the Java API.
The best techniques I've used to try to get the point across are:
- Test isolation (see easymock comment above)
- Ease of writing/using wrapper classes (think of all of the InputStream classes that take an InputStream in the constructor)
- Ease of proxying (the dynamic proxy only works on interfaces)
- Spring RMI goodness :-)
- Simplification of work distribution (team members decide on an interface, one goes off to use, the other to implement)
The list goes on. At some point, some thing will click with them and they'll be happy.
If the worry is over a junior developer creating too many interfaces, I'd rather see that than the opposite. Junior devs will make mistakes, lets steer those mistakes into a least harm form.
Posted by: Paul | Nov 27, 2007 at 00:50
I think every would-be Java programmer should prepare for and take the Sun certification test. This should be done prior to looking for work as a Java programmer. At the very least it should be done during the first months on the job instead of actual coding. One who follows this path will be a better Java programmer than the overwhelming majority Java programmers I know, and I know many.
Posted by: Jonathan | Nov 27, 2007 at 09:56
Jonathan, I can agree that there are many developers which are below the certification level. However, I believe training and certifications will never replace experience in such cases. As I noted in my post (and commenters seem to agree), there is no set of well defined rules one may apply when designing interfaces. There are some rules but they should be backed with some healthy intuition. Such intuition cannot be taught. It is something you develop over time. That's why mentoring and OTJ training is far more important, IMHO.
But, that's not important. The hi-tech market is prospering. Which means it doesn't take much to find a job (at least in Israel).
Posted by: Zviki Cohen | Nov 27, 2007 at 11:03
very good blog and replies too.Thanks.
Posted by: RSR | Nov 28, 2007 at 16:25