How To Write Good API Documentation
To write good class- and method- level documentation for a public API 1, keep the following in mind:
Good documentation writers are cross-functional: good engineers, but also good communicators, like writers and UX designers, who know how to structure and present information in a way that gets the message across. They can see it from the other side of the table.
Good documentation, like good anything, takes time. It won’t be done next sprint. Be patient with yourself to learn this skill.
Good documentation describes the preconditions: what you need to do before calling the method. For example, if you have a
ShoppingCart.addItem(item)
method, the documentation might say “Before calling this function, ensure that the item is not sold out.”Good documentation describes the postconditions: what will happen after the method returns. Such as, “After this function returns,
ShoppingCart.isReadyToOrder()
will be true.”The pre- and post-conditions constitute a contract: you do this, and I’ll then do that for you.
Some situations can be handled in multiple ways. For example, if you add something that’s already in the cart,
addItem()
might conceivably fail, or it might increment the number of units of that item. Both are valid approaches. Readers shouldn’t have to guess which approach the method takes. The documentation should say so.Good documentation is written from the user’s point of view, not that of the developers building the API. This is similar to how good UX is designed from the user’s point of view. Good documentation says what a method does, not how it does it. For example, my washing machine has a super clean mode that does extra cleaning for soiled clothes (what). The manual does not say that it increases the voltage to the impeller (how). When you write documentation, take a step back, think about it from the user’s point of view, ask yourself what you’re assuming the reader knows that he may not, and clarify it. Start from the beginning. Documentation writers know the system in depth. This is both a blessing and a curse. A blessing, since it gives them the knowledge needed to write good documentation. A curse, since they often jump to the middle without setting the proper context. For example, if I say that “The Enterprise-E is equipped with quantum torpedoes”, you may not know what I’m talking about. But if I say, “In the show Star Trek, the starship Enterprise-E is equipped with multiple weapons, one of which is quantum torpedoes”, it’s understandable. Show the documentation you’ve written to someone who has no idea about your company and ask him to describe what a method does. If he’s not sure, or if he gets it wrong, you need to improve your documentation.
Good documentation says what something doesn’t do, thus preventing common mistakes. For example, the aforementioned
ShoppingCart.addItem(item)
might say, “Does not recalculate the total value; for that, callrecalculate()
.”Good documentation assumes no prior knowledge. It lets you start reading anywhere without having to understand other classes. API documentation is not a novel, which you read from the beginning to the end. It should be a web of links that you can navigate starting anywhere, like Wikipedia.
Most classes, methods and packages should be documented.
Good documentation encapsulates: you shouldn’t have to read the documentation for each method in a class to infer what the class does. Instead, you should be able to start with the class’s documentation and decide whether you’re interested in the class. Only if you’re interested should go one level deeper and read individual methods’ documentation. Similarly, you should be able to read a package’s documentation to decide whether the package as a whole is relevant to what you’re trying to do, before diving deep into individual classes in it. Good documentation is like having an Invoices folder on your computer: you don’t have to open it to know that it contains invoices. Bad documentation is like a folder named New Folder — you don’t know what it contains unless you open it and look through the contents one by one.
APIs are often layered, where a higher-level API offers ease of use, and a lower-level API offers flexibility. In such cases, the documentation for the higher-level API should say, “If you need to customise A, B or C, use <Lower Level API> instead.” And the documentation for the lower-level API should say, “This class lets you customise A, B and C. If you don’t need this flexibility, it’s simpler to use <Higher Level API> instead.”
Good documentation uses consistent terms: don’t refer to the same thing as an “attachment” in some places and a “file” in others. Readers will wonder if they’re different things.
Bad documentation repeats what the name and signature say, like
Message.getUserId()
saying “Returns the user ID”. This doesn’t add value. Either say something useful like “Returns the user ID of the sender of this message” or remove it.Bad documentation has verbiage like “This class contains methods that transfer money to a recipient”. Every class contains methods, so you don’t need to say it. Similarly, where else is money transferred except to a recipient? Just say “Transfers money”. As Strunk put it so eloquently, a sentence should contain no unnecessary words for the same reason that a machine no unnecessary parts.
Writing documentation often exposes other opportunities for improvement. For example, if you have a
Message.getUserId()
and you find yourself writing documentation to explain that it returns the sender’s ID rather than the receiver’s, stop and consider renaming it toMessage.getSenderId()
so that it’s self-explanatory. As another example, if you find it hard to explain what a class does, it might be doing a bunch of unrelated things that should be split into multiple classes.APIs sometimes have methods that are for internal use but accidentally exposed in the API, or which cause problems like a crash. If a class or method should not be used, the documentation should say so.
There are other kinds of documentation like guides, tutorials, video walkthroughs, and so on, which I don’t cover in this blog post.