I am a big fan of the APR versioning guidelines, but there is an element they don't capture well somewhere between major (backwards incompat change) and minor (forward incompat change) in Java. If you follow the, generally recommended practice of exposing things via interfaces (pure virtual classes), you have opened the door for users to implement those interfaces.
In a C-style world, adding a function to a library would bump you from 1.6 to 1.7, using APR guidelines. In an interface-driven Java-style world, adding a method to an interface would bump you from 1.6 to 2.0. Or would it?
To take a concrete example, a coworker (thanks Jax!) recently
re-added first class support for callable statements to jDBI. jDBI
uses a Handle interface to expose operations against a
database. It has gained a method:
public <ReturnType> Call<ReturnType> createCall(String callableSql,
CallableStatementMapper<ReturnType> mapper);
If you implement this interface, the change is backwards
incompatible. An implementation of Handle made against
2.2.2 will not compile against this. On the other hand, the intent
of the library is not for people to implement Handle,
it is to expose the libraries functionality. It is almost a
header file.
So, 2.3 or 3.0?
writebacks...
Rule is actually simple. If this interface is declared in "internal" packages (non-API) then it is backward compatible change. Unfortunately there is currently no way in Java to explicitly specify what packages/classes are internal. OSGi handles this using "Export-Package" attribute and jsr277/294 is trying to bring a first class support for this into Java. BTW, there are some neat API tools in Eclipse 3.4 that help to detect things like API incompatibility and API leakage, but they only work for OSGi bundles at the moment.
I would say 2.3. I don't interpret "forward incompatible change" as "existing code still compiles without change", but rather "behavior of existing code does not change". You may need to add implementations for new methods (which could be as simple as "throw new UnsupportedOperationException()"), but you don't have to change any of the other code in your implementing class.
This problem has existed in the JDK when some methods were added to java.sql.Connection in 1.4, thus breaking all connection pool implementations. IIRC, Sun's rationale was that binary compatibility of existing code was kept (i.e. you could run pre-1.4 JDBC code on a 1.4 JVM), and that writing your own implementation of this interface was something only tool vendors or very advanced developers would do, thus not causing much harm. So I would say 2.3, with a warning that some interfaces have evolved and that _some_ code may need to be updated to compile. And clearly state in the Handle javadocs that it's an internal interface :-)
comment...