To All API and Library Designers

Posted by Berin Loritsch Wed, 23 Jun 2010 12:42:00 GMT

Creating APIs and libraries can be a difficult task. There are many concerns that you have to worry about such as design consistency, correctness, function, performance, security, and the list goes on. Something that typically gets lost in the list of concerns is usability . I know you might be thinking I’m nuts because APIs and libraries don’t have a graphical user interface. Yet they do have a user interface. The users of APIs and libraries are developers, and they use the exposed functionality provided by the API. Here are a few pointers that will cause developers to shout your praises rather than curse your name:

  • Error messages/Exceptions should be clear
  • Design patterns should be consistent
  • Documentation should be useful

I’ll spend a little more on each topic to flesh out what I mean.

Error messages should be clear

Whether your language uses exceptions or another method of notification; the user of your API needs to know if they are the cause of the problem, and more importantly what they can do to fix it. Let’s take the example of bad parameters. They happen, particularly when a user doesn’t understand what is written in the API docs or it’s just an honest mistake. When a function has a half dozen parameters, it really helps to know which parameter is causing the problem. A generic “invalid parameter exception” with no indication of which parameter isn’t very helpful. If the parameter has to be within a certain range, say so.

There’s nothing more frustrating than spending a whole day trying to figure out what you are doing wrong, searching forums for possible clues, only to turn up empty. The more you can help your users (the developer) stay focused on writing software, the better. If an exception is caused by something outside of your control, it really helps to give that information back to the developer. They may be able to fix something that your library depends on.

Design patterns should be consistent

Whether you are using formal design patterns or simply a programming idiom to help convey the intent of the API, use it the same way throughout your API. There is nothing more confusing than having exceptions to the rule. We get enough of that learning English, we don’t need it in our APIs as well. The problem with exceptions is that they raise the mental complexity of the API. Every time a developer accesses a function, they have to consider is this function operates differently (or worse: which difference applies here?).

There’s no question that designing a consistent API is very difficult. The nature of the problem is trying to find an abstraction that helps the developer solve a problem. The problem is that if you choose the wrong abstraction you will make it harder to solve the problem or write the API. It’s a delicate balance. However, if you find yourself always needing to break your abstraction in a couple of places, perhaps you chose the wrong one to begin with?

Documentation should be useful

Developers really need two types of documentation. Many API writers recognize the importance of API docs (such as JavaDocs or .Net Docs). In order for these to be useful, the person referring to the documentation needs to know more than the parameters and the name of the function. They need to know what the function does for them, and if there are related functions that handle different tasks what they are. In an API reference, that is sufficient. You just need to refresh the developer’s memory, and help point them in the best direction if there are related (but different) functions.

What usually gets lost is describing the design patterns or abstraction the API is using. It’s one thing to know what the functions are, it’s quite another to be able to put them together in the right combination. Writing down the API design approach also helps the API developers understand how they are supposed to be solving the problem. Also, by writing down the API approach, you see just how difficult it is to convey. If it is too hard to explain, it is too hard to understand, and far too hard to use. Without this foundation, the examples of how to use the API make a lot more sense.

Conclusion

The three concerns I listed here are the top frustrations I have with any given platform. Whether it’s Java’s extensive APIs, the .Net library, Ruby’s API, etc. I’ve come across violations in at least one of the three concerns. My biggest frustration at the moment has to deal with bad or confusing error messages. The worst thing you can do as an API writer is have your users play “bring me a rock” with your API. It really helps to know that parameter X is invalid because it is not within the range of Y-Z. It does not help to know that at least one parameter in a list of seven is invalid: go figure out which one and how to fix it yourself. Additionally, if the network gets dropped and you no longer have a connection to a server, that information needs to make it to the developer instead of other exceptions that are just a consequence. For example if the problem is a file permissions problem, throwing a null pointer exception only confuses the user. They will quite rightly think you don’t know what you are doing. Understandably, proper exception handling is important. Which exceptions do you expose, and which do you handle internally? When the system breaks are you doing something unexpected as a fail-over? Java’s Remote Method Invocation API failed terribly in this manner. Instead of completely failing to call the remote object, it would silently fail over to an unencrypted HTTP tunneling approach first—even if the original connection was encrypted. That’s an epic security failure. Be reasonable, and sometimes it is better to fail completely than it is to fail over to something insecure without notifying the developer in any way.