The Art of API development
»From the programming part of the brain.
Writing a good API is not an easy task. Like any other piece of software, you need time to talk about requirements, get some design going on a whiteboard, and do lots and lots of testing. If you work hard, at the end of the day, you’ll have another component to add to your arsenal of software, which you’ll be glad to have when you run into a similar problem down the road. I’ve learned some good and bad things about API design, mostly by practice (read: making mistakes) so I thought share some thoughts about what I think makes a good API. If there’s a flaw or a gaping void, please leave a comment, as I’d like to hear your thoughts on the subject.
- Be Focused. You’ve got to focus on the problem. To do this well, you must do two things. First, you have to dig for those requirements. They aren’t going to come to you, so you have to go after them, which leads me to the second point. Speak with your intended audience. Become intimate with the problems they are trying to solve. Bounce ideas off each other and listen to feedback.
- Document. Be fanatical about documentation. Document everything from HTML-friendly Javadoc at the method, class, and interface level, to suggested working examples of how your API should be used in your project’s homepage, release notes, and/or blog. Document exceptions, parameters, constructors, and packages (overview.html). Tossing in an image of the “big picture” won’t hurt. Document intention, as it’s far more valuable to know what the programmer intended. Don’t just duplicate your source code in the documentation, otherwise you’re just repeating yourself and you run the risk of having the documentation drift out of sync with the source code.
- Be Intuitive and Simple. Did you read the previous point? Did you document every iota of your API inside and out? Do you even have a blog that you use to post advice on how to best use your API? Great. By the way, nobody is going to read it, well not at the very beginning anyway. You have to apply the “don’t make me think” approach to your API. It’s like a really well polished UI that requires very little training and is easy to pick up. If you make it intuitive to use, people will get a good impression with it from the start. Similarly, you need to get that initial positive reaction to your API and one way to do this is by making it intuitive to use, even without documentation. Things are intuitive if they fit into a person’s mental model. Keep things simple and people will love you for it.
- Ask (Hard) Questions. Should this API support generics? The
enumtype instead of aStringobject? Should my factories be singleton objects lying around in memory forever? Should I return null, throw an (unchecked or checked) exception, or return an empty, non-null array of zero length? How much boilerplate code should I place in an abstract class? Will this be thread-safe? Immutable and reusable? between n-threads? Should I load all limited resources up front and manage them in a pool or a lazily initialize them? The answers will vary slightly by kind of API you’re developing and the requirements you have, but make sure you ask them. - Use Interfaces. In your API, always make the type as generalized as possible. If you use
Mapinstead ofHashtableyou insulate yourself against future changes to the choice ofMapimplementations. Similarly, your Super XML/REST parser should accept anIXmlParserinstead of aConcreteDomXmlParseror aConcreteSaxXmlParser; let your users decide which strategy to use. Now, don’t go refactoring every method in every class you have out to an interface. Figure out what can be reused and remember to keep details of how an implementation works to a minimum. - Eat your own dog food. That’s right, you wrote an API, now write a program that uses the API. Better yet, write three. If you’re writing an API that manipulates images, write a quick desktop app that can return the image as an SVG, or a web app that returns it as a JPG. Or better yet, do both. An API should be about how the user thinks, eating your own dog food forces you to do this. If you’re releasing an XML/RESTful API, pick a language and write an XML-to-Object parser and maybe even an Object-to-XML parser. By doing this, you’ll find out just how easy it is to parse your own XML, or figure out that a service is returning too much XML, or if there are too many inconsistencies, etc. Remember, your APIs first user will be your test cases. Write them early and assert everything. If you find your API too cumbersome to use or too complicated to test, you may want to rethink some decisions. Refactoring makes this process trivial.
- Minimize visibility. Dealing with visibility is a tricky issue. On one hand you don’t want to make everything private since it may conflict with the reusability or extendability factors of your API, but on the other you don’t want users of your API doing things that they shouldn’t be doing. The argument can be made either to make everything
protectedto maximize reusability or to minimize visibility and increase scope later, if the need arises. I take the latter, though I’ve heard good reasons for the former. Either way, you’re going to have to document those reasons; if a class or a method is not meant to subclassed, specialized, or overridden kindly mention why. Always deliberately pay attention to the scope your methods and variables have. - Have a friendly license. Choose a license that deliberately communicates your intent. If you want to be friendly to businesses, make sure you find a license that let’s developers take your API, build something cool on top of it, and not have to worry about any legal repercussions. If you want to enforce the rule that all software built on top of your API is to be freely available, there are licenses for that too. Either way, you’ll want to make sure your intent is clearly communicated.
- Grow. Finally, if you’ve decided to release your software to the public, thank you. Doing this is no easy task, especially if you have something that people really want to use. This final point is meant to highlight the relationship you’re going to have with the community. Make sure you a process (forum, blog, newsgroup, defect tracker, wiki, etc) that let’s you listen and respond to the feedback of your users. Just like any social software community (frameworks like JSF, platforms like Eclipse, OSes like Linux) you have to listen to your users, tweak and retweak the API so that it can grow. Be careful not to go feature crazy, otherwise you’ll swamp yourself with work, violate the principle of simplicity, go outside the bounds of your original problem, and end up with something completely unmanageable.
These are just a few heuristics I’ve found work best for me. You shouldn’t blatantly violate them, but you also shouldn’t follow them blindly. You’re going to find that achieving API nirvana is next to impossible, but you should try anyway.
Updated a few hours later: Wrote closing statement & fixed grammar.