Don't Skimp on Documentation

JAN 18

When you build a product for technical users, documentation is extremely important. If people can't figure out how to use your product you won't have any users no matter how amazing your product actually is.

Poor documentation will increase the number of confused developers and subsequent support requests that you receive. Just like quick-and-dirty coding decisions can lead to technical debt, poor documentation can lead to operational debt.

The repercussions of sloppy documentation are twofold: some fraction of developers who would otherwise have used your product won't use it, and those that do will require more attention from your support team.

Users are busy

Imagine you need to complete a math assignment using LaTeX and someone suggests you read you read TeX: The Program. Though it is a great book, your goal is to produce a PDF with your homework properly formatted, not to read a novel. The vast majority of people who visit your documentation are there not to learn more about your fascinating product. They are there to find out how to get something done, like write a 2-Factor auth library, or figure out how to receive calls from a fake girlfriend.

You can't expect that users will actually read any of your documentation. Many users will try to copy and paste the exact contents of a code box into a text file or command prompt and expect it to run, without reading any of the surrounding comments. You cannot assume your users have any context besides what you put in a code sample and maybe one or two sentences above or below. Let's walk through an example, using an old snippet from the twilio-python API library.

# How to make a call
client = TwilioRestClient()
calls = client.calls.list(statsus=Call.IN_PROGRESS)
call = client.calls.create(to="9991231234", from_="9991231234",
                           url="http://foo.com/call.xml")

This will cause a number of problems for the first time Twilio developer.

  • Their script will choke unless they've remembered to add a from twilio.rest import TwilioRestClient line at the top of the file.

  • Initializing the TwilioRestClient with no parameters means that the TwilioRestClient constructor will look in the user's environment for variables named TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN. The documentation for these parameters is in a different location. Better to be explicit:

ACCOUNT_SID = "ACXXXXXXXX"
AUTH_TOKEN = "dddddddddddd"
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
  • The argument to the list method, statsus is spelled incorrectly, so the parameter will not be passed correctly.

  • Unless the user knows about TwiML and changes the url parameter, the first thing the user will hear when the call connects is "An application error has occurred." There's no context in that error to learn about TwiML or understand the error. Instead of linking to a url that will 404, use something that actually successfully demonstrates your product in action:

call = client.calls.create(to="9991231234", from_="9991231234"
           url="http://demo.twilio.com/welcome/")

Our example is now more robust and has much needed context:

from twilio.rest import TwilioRestClient

# How to make a call
ACCOUNT_SID = "ACXXXXXXXXXXX"
AUTH_TOKEN = "dddddddddddd"
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
calls = client.calls.list(status=Call.IN_PROGRESS)
call = client.calls.create(to="9991231234", from_="9991231234",
           url="http://demo.twilio.com/welcome/")

Better error messages

When things are broken, it's important to tell people what exactly went wrong and how to fix it. Some things you can't control very well, such as a user running pip install twilio and getting a -bash: pip: command not found error.

That message gives no hint at how to fix the problem, and you can't change that. But you should anticipate, and provide explicit messages for, errors where you can control the output shown to the user. Continuing with the example from above, here's what the error message used to look like:

>>> from twilio.rest import TwilioRestClient
>>> client = TwilioRestClient()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.6/site-packages/twilio/rest/__init__.py", line 110, in __init__
twilio.TwilioException: 
Twilio could not find your account credentials.

That doesn't explain where you should actually put your credentials. A better message:

>>> from twilio.rest import TwilioRestClient
>>> client = TwilioRestClient()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.6/site-packages/twilio/rest/__init__.py", line 110, in __init__
twilio.TwilioException: 
Twilio could not find your account credentials. Pass them into the
TwilioRestClient constructor like this:

  client = TwilioRestClient(account='ACCOUNTS_SID', token='AUTH_TOKEN')

Or add your credentials to your shell environment. On OSX or Linux, add
the following to your .bashrc file

  TWILIO_ACCOUNT_SID=AC3813535560204085626521
  TWILIO_AUTH_TOKEN=2flnf5tdp7so0lmfdu3d7wod

Replace the values for the Account SID and auth token with the values 
from your Twilio Account at https://www.twilio.com/user/account.

Your error messages should always explain how to solve the problem raised by the error. Otherwise, they'll lead to support tickets (an increased expense), and/or frustration (lost revenue).

Users are coming from Google

Over 50% of the visitors to Twilio's documentation come straight from Google, and your documentation probably has a similarly high number. This has several interesting implications.

First, you need to think about SEO for everything that you write. Specifically, you should make sure that:

  • documentation pages have exactly one <h1> tag.

  • the <h1> tag fully describes the content of the page.

  • the page's <meta description> tag describes the content of the page.

  • you are linking to other pages of your documentation often, using relevant keywords. Instead of linking like this: "Click here to read our SMS sending documentation", link on the keyword, like this: "For more information, read our documentation on sending SMS messages."

  • all anchors have title attributes (extra text when you hover over the link, like this: <a href="http://www.example.com" title="Hello!">). This is good both for SEO and for accessibility/usability.

  • all images have alt text (needed for accessibility, and so Google will know what's on the page).

Find other tips in Google's great Search Engine Optimization Starter Guide.

Furthermore, users are not "discovering" your documentation by going to the homepage and navigating through the tree. They are landing on the specific page that they want to get to, via Google. So you can't expect that users will see anything outside of the page they land on; each page needs to be a self contained unit of awesomeness.

If you don't think about SEO for your content, you may be getting outranked for key terms by content farms.

You are busy

Let's face it, you've got a million things on your plate, and if you leave the documentation until the end, it won't be as awesome as it should be. That's why you should write your documentation first, before you start coding. This means you're doing it while you're still really excited about the project. It also forces you to think through some of the decisions you will make, before you start writing code for things that you're not going to implement.

Writing the documentation first will also help you program to an interface, not to an implementation.

This is called Readme Driven Development, and it can help you write great documentation.

Bottom Line: Writing effective documention requires you to understand who your user is, how they behave and how they are finding answers to their questions. You also need to dedicate time in your product development cycle to writing documentation good enough so that users can figure out your product.

Examples of great documentation in the wild

Posted by Kevin Burke on January 18, 2012