Java API Design – Making Breaking API Changes Easy for Library Users

api-designjavalibrariesversioning

In the past, I used the standard way of adding @Deprecated annotations to API methods which will be removed in a later version.

Now I am preparing a major version for a library, with many API parts removed and renamed.

To make the transition easier for existing users, maybe it could be helpful if the new library version can be used side-by-side with the old version.

Advantages

  • dynamic switching between version can be implemented
  • applications can fall back to the previous version if bugs are found in the new version (useful in beta phase)

To do this, I could simply move the new library version to a new package from com.mycompany.library to com.mycompany.library.v2

Is this a common practice or are there other recommendations for such side-by-side usage of Java libraries?


Background:

the library is a simple document converter. So besides a convert(in, out) mehtod, it has many configuration properties and some event handlers. If I provide side-by-side usage, consumers could dynamically instantiate and configure them:

if (useVersion2) {
  com.mycompany.library.v2.Converter c = new com.mycompany.library.v2.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out); 
} else {
  com.mycompany.library.Converter c = new com.mycompany.library.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out);
}

(question moved from https://stackoverflow.com/questions/37192945/)

Best Answer

This approach is rather common. It allows a smooth transition to a new API, and a safe evolution towards new implementations.

Of course, the if/then approach, as highlighted by Laiv in his answer, has some drawbacks. It's tedious. It's easy to forget or to mixup things. Ideally, the use of wrappers, factories or adapters could provide some nicer alternatives. But often, the simpler is the better.

Martin Fowler and Pete Hogdson have recently theorized about this topic in an excellent article in which they describe what they call "feature toggle patterns". It might interest you as different implementation strategies - such as the use of a "toggle router" - and usage scenarios are described in full details.

Note: personally I'm not found of feature toggles. Coming from C++ world I prefer the easy and robust alternative using namespace aliases and using clauses to choose at compile time the version to use. But it's language specific, and furthermore it doesn't allow for dynamic configuration as the feature toggles. So as said, sometimes, the simpler is the better ;-)

Related Topic