Documentation-Driven API Design
Documentation-driven design is not a new idea… just search Google. It has, however, usually been advocated as a means for improving the quality of the documentation. I believe it is far more useful than that — it can influence the design process.
I once heard a documentation writer at Google lament that documentation was always written during the last phase of product development. Writing the documentation, he pointed out, made it perfectly clear where the worst UX problems in the product were — they always corresponded to whichever aspects of the product required the most explanation. Unfortunately, by the time the documentation was being written it was too late to change the product. He was right. Anything you struggle to explain is designed poorly.
This insight is useful for any kind of design practice, but I have personally found it most valuable when designing APIs. Open source libraries, frameworks, web services, SDKs, modules of a large system, even the interfaces of single classes — they all present an API.
I think we can all agree that:
- A well-designed API is easy to understand.
- A well-designed API is easy to get started with.
- A well-designed API requires you to learn a minimum of new concepts, rules or terminology.
- A well-designed API leverages concepts that you already know and works in familiar, predictable ways.
- A well-designed API requires as little documentation as possible.
- A well-designed API obeys the Principle of Least Surprise.
There’s a lot more to API design than just these qualities, but many APIs fail to meet even these standards. It’s easy to see why. When engineers develop software, they tend to work backwards from the problem to a technical solution and consider the API last. Indeed, some engineers never seem to consider the API at all — they just settle for whichever API emerges. That’s like writing a novel and wanting to publish the first draft.
You’re only halfway done when you arrive at a technical solution for the problem. At this point you have solved the challenge of implementation — now you need to change gears and focus on the API.
API design is a User Experience problem where the user is the engineer who will use the API. An engineer faces the UX aspects of API design without a designer at their side.
Like any design problem, success in API design turns upon empathy for the user. An engineer who approaches an API for the first time needs to build a mental model of how your API works. They’ll have questions like:
- How do I do X?
- What’s the best way to do X?
- Am I allowed to do Y?
- What can go wrong? What are the edge cases?
- Do I need to do X before I can do Y?
- If I do X, do I need to do Y later?
- Can I do X, Y, Z in any order?
- What are the side effects of Y?
- What are the performance and resource usage implications of doing X?
- etc., etc.
A well-designed API offers a simple, learnable mental model. This is particularly difficult for the API designer. By it’s very nature, creating software involves immersing yourself in the problem at hand. This makes it difficult to take a step back and see through the eyes of a newcomer. This is where documentation-driven design becomes useful.
Here’s how it works:
- Write the documentation for the API. You can do this as you design an API or later if you’d like to rework an existing API. Wherever the documentation becomes complicated or difficult to write, revisit the design. This process works because it is easier to spot complexity in the documentation than in the code.
- For example, inconsistencies in your API becomes painfully clear when writing documentation. Two classes might have methods with similar names but that work in very different ways. Or they might be inconsistent about how permissive they are about their inputs, or around thread-safety, or whether errors throw exceptions or affect return values, etc., etc. Writing documentation places you in the mindset to spot these issues.
- Another simple example is when the documentation for a class or method or property don’t align with it’s name. Naming is hard; documentation helps identify where you’ve gone astray.
- Also look for terms in your documentation that have a meaning specific to your API. These terms correspond to concepts that you’re requiring the user to learn. Try to minimize these — and not just by rewriting the documentation, but by reworking the API itself. The cognitive burden of an API is a function of the square of the number of concepts that it requires the user to learn — and engineers are rightfully wary of assuming that burden.
- Documentation-driven design depends on the ability to write good documentation, but simply the act of focusing on the documentation will help you cultivate empathy for the user. You’ll try to anticipate the ways a user might misunderstand your API. You’ll include warnings about gotchas and recommendations on best practices. These translate directly into ways your API can be improved.
- In documentation-driven design, you should define documentation broadly. Show your API to others, whether in the form of a PR, a formal presentation or through hallway testing. Look at what takes the most time to explain. Pay attention to the questions your audience asks. Talk to the audience afterward and probe for misunderstandings. This will help pinpoint where the API could be improved.
- Best of all, if your API already has users, pay close attention to what they find hard to understand — and what they complain about. If someone opens a Github issue due to a misunderstanding, don’t just close the issue — consider changing the API to prevent that misunderstanding. Thanks to everyone who has ever complained to me about an API I created; your comments (hopefully) helped.
API design is hard. It takes time and deliberate effort. A well-designed API has a deceptive simplicity, as though its design were inevitable, but it’s far more likely that it was the outcome of multiple iterations. Documentation-driven design offers a clear, actionable way to guide that process.
The simplest way to get started with documentation-driven design is to wait until you’re faced with a tough choice in the API design process. Try writing the documentation for both options — this will help clarify the tradeoffs at hand.
Lastly, in API design simplicity is not a virtue in and of itself. Documentation-driven design isn’t about simplifying your APIs. The goal is to achieve clarity, consistency, and elegance.