I’ve been working with the writers of a popular framework lately on some issues with a release. One of the things we ran into was that the semantics of a method changed with the new release and this in turn made our application stop working. This got me to thinking about APIs in general. It brought me back to the first time I read “How to Design a Good API and Why it Matters,” by Joshua Bloch. This presentation goes over a lot of the design strategies around public APIs and one slide in particular put into words something I have been doing for a long time, “Public APIs are forever – one chance to get it right”. This is also followed up a few slides later with, “When in doubt leave it out”.
Why is this so important in API design? Because if you provide a class or a method, people will use it AND they will expect it to always work the same way no matter how many versions you go through. The only chance you ever have of removing or changing a method is when you do a “ball-buster” release.
This issue came up on this framework I’ve been working with (I’m leaving names out intentionally). I was using an API call to do a bit of work that otherwise was quite difficult and cumbersome. This API call removed a lot of code and made things much faster to develop. We actually found the API by doing a bit of Googling, which means that many others are using this API as well. During the latest release of said framework this API call stopped working as it had before and how its documentation stated. After a submitting a bug and a little discussion I was informed that I should refactor everything and do it the long way (well of course that will work but I used the API method because that way sucks) and :
(The API calls) are supposed to be a last-resort fallback only (snip). We just don’t recommend (them) for such needs in the first place.
I went back and looked at the JavaDoc and of course down at the bottom of the class comment it said:
However, this approach should not be used when there is a reasonable alternative.
This is not a good API design. You can document public API classes and methods telling people not to use them until your hands fall off, but guess what, people are going to use them if it makes life simpler or there is no other way. Additionally, you can’t tell someone who has been using an API that you made public that you don’t want to support it. You’re the one who opened the API up and therefore you took on all responsibilities in maintenance. Therefore, my rule of thumb is, don’t open things to the public if you:
- Don’t want to support it
- Don’t think it should be used
This is the same reason that deprecated is pretty much a worthless concept overall. Unless you have control over all the code that compiles against a deprecated method, you can’t expect people to stop using it because it costs money and usually a lot of it, to go back and change code. Deprecation usually says to me, “oops my bad!”. The only help that deprecation provides is getting folks ready for “ball-buster” releases. I won’t get into those things, but let’s just say that most well known APIs don’t ever do them.
If you intend to write a public API, realize up front what you are doing and don’t assume things about your users. Stay away from deprecation and understand what maintenance really means. So, go forth and design good APIs.