Tuesday, January 17, 2006

Interfaces Overvalued in Java API Design

In Java API Design Guidelines, Eamonn McManus says:
There's a certain style of API design that's very popular in the Java world, where everything is expressed in terms of Java interfaces (as opposed to classes). Interfaces have their place, but it is basically never a good idea for an entire API to be expressed in terms of them. A type should only be an interface if you have a good reason for it to be.

McManus goes on to explain the problems with interfaces and to list the cases where interfaces make sense. This is the best explanation of the tradeoffs I have seen anywhere.

Of course, the article isn't just about interfaces. It includes lots of other guidelines for Java API design. Good stuff.
 

8 comments:

Pete said...

It's a good article and I agree with a lot of it but he doesn't flush out the comment on abstract classes well, as relates to his point on 'Interfaces cannot evolve'. What constitutes an abstract class is pretty broad. I would argue that one should lean toward a 'Pure' abstract class rather than a flushed out one.

I have other thoughts, but I've already spent too long trying to get that one out...

Dave Delay said...

By "pure" abstract class I assume you mean a class where all the methods are abstract. Isn't that just an interface by a different name? The only difference is it doesn't let implementors pick their superclass.

I think the only reason for using an abstract class is when you want all subclasses to share the implementation of some methods, but you want to defer the implementation of other methods to the subclasses. "Pure" abstract classes don't seem to have any advantage over interfaces.

But I agree he could have explained the source and binary compatibility issues better. I would expect a new abstract method to result in the same compatibility problems as a new interface method.

Pete said...

I got caught up by his choice of the word abstract. "if you use an abstract class instead of an interface you don't have this problem". As you point out, that's not quite the case. Pure was also a bad word choice. How about Blank instead. You would still need a factory to build an instance with an implementation but it then has most of the good attributes of an interface without the difficulties of compatibility. Something like:

public class Foo {

protected Foo() {
}

public bool isMoo() {
return false;
}

public SomeThing resolve(FooBoo fooBoo) {
return null;
}
}

Bob said...

Looks like a good article but I think he missed a few things on interfaces:

First, he says "it is basically never a good idea for an entire API to be expressed in terms of them". If your API needs to define exceptions then not only is "never a good idea" but it's also not possible. Look at the DOM API. It is all interfaces except for exceptions.

Second, for reasons for a type to be an interface, he doesn't mention the API/SPI model that's fairly common -- and useful. A good example of this is JDBC.

The pendulum swings back and forth. A pure interface model where even basic types are defined as interfaces can be bad, especially since it can make the API user's life painful. But only using interfaces very sparingly can be problematic as well.

Dave Delay said...

Bob, I have the answer. For any API, exactly 42% of the types should be classes. The rest should be interfaces. ;-)

Bob said...

42. Perfect. Now all that's needed is for someone to write a PMD rule to enforce this and you're good to go.

Violators of the Dave Delay Golden Ratio of Class/Interfaces should have their checkin privileges revoked.

m@ said...

Eamonn McManus' analysis of interfaces is just dumb. All of his points, binary compatibility, requiring factories for instances, cannot be serialized and interfaces can be implemented by anyone, these are all so obvious and in no way are they valid reasons not to use them.

Technically interfaces can be implemented by anyone but there are ways to discourage this in some cases simply by declaring so in the Javadoc. API is not complete without the contract definition.

Because I need a factory to build interfaces I shouldn't use them? That's silly. It's the proper way to implement the factory design pattern. And there are many ways to evolve interfaces.

I won’t even get started on his "good reasons" for using interfaces

Dave Delay said...

Matt, he didn't say never use an interface. He said use them only when there is a good reason. There are plenty of great reasons to use interfaces, but when an API is all interfaces, it can be difficult to use and difficult to change over time. As a minimum, API developers need to understand the trade-offs. I don't think everyone does.