Geek Alot
Posts: 2
Nickname: geekalot
Registered: Jan, 2006
|
|
Re: Java API Design Guidelines
|
Posted: Jan 4, 2006 7:03 PM
|
|
Thanks for the interesting posting! Here are a few more comments on that perennial topic of "What are interfaces good for anyway":
I agree that a package containing a beautiful set of interfaces but no factory methods that return instances of those interfaces or classes that implement those interfaces is confusing to the programmer. Such a package is only useful if there are providers that offer implementations. The trouble is that often there are many providers and many implementations to choose from and configuring your program to use the right one can be confusing. E.g. java.sql or org.xml.sax are useful only in an environment containing real implementations.
For some packages, like org.xml.sax, one can imagine an ultimate implementation and wish we just had that and didn't have to worry about the complexity in having 23 different XML parsers, while for others, like java.sql and java.util.Map, there really can be no ultimate implementation and we just have to live with the complexity.
You mention that if String were an interface one would have to worry that length() might return a negative number. I don't buy this. A well documented interface contains an informal specification of what the classes that implement that interface represent and what the methods of that interface are supposed to do. A length() method in an interface should specify the meaning of negative value or specify that it is not allowed. Of course that specification is informal and someone could implement the interface incorrectly, but then the specification of a class method also informal and someone could implement that incorrectly as well. The only difference is that a final class may have only one incorrect implementation while an interface may have many incorrect implementations!
You mention implementations that cheat and cast parameters with interface types to the non-public implementation class. That is a general problem with O-O languages, packages containing classes meant to be implemented together, and methods of one class that accept abstract objects of a related class.
For example, java.sql.Connection.rollback() takes a java.sql.Savepoint as a parameter. That Savepoint parameter must have been created by java.sql.Connection.setSavepoint() on the same connection used to issue the rollback. The implementation of rollback() is justified in casting the Savepoint into its private implementation class. That is not cheating, that is just the way the game is played. You cannot supply just a Savepoint implementation and expect it to work with other Connection implementations. You have to supply the whole works: Connection and Savepoint (and PreparedStatement and ...).
Interfaces can evolve, they can evolve by extension. The new version of an interface can simply extend the old version. The trouble is that users don't like having to type an ugly interface names like java.sql.Connection-3-0, even though careful dependency mavens think that it is great. One solution is: Don't use Interfaces in API's, use them in SPI's.
The API can be a set of final classes which act as a bridge to the underlying classes that implement particular versions of the SPI interfaces. E.g. A java.sql.Connection could be a simple bridge class that would provide all of the JDBC 3.0 functionality on top of either java.sql.spi.Connection-1.0, java.sql.spi.Connection-2.0 or java.sql.spi.Connection-3.0. If the driver only supports JDBC 2.0, the new 3.0 methods would raise an exception.
Might this same trick handle serialization?
Cheers!
|
|