More professionals in computing should be offering their expertise in written form. Too many projects are currently hampered by missing or uninspired documentation, notably by its inability to represent real-life issues and by its lack of conceptual background. And when employers or community members urge programmers to write, the unwilling authors approach the task too often with disdain and even dread.
I believe that more programmers and computing experts would contribute to our common store of knowledge if they knew the principles that make documentation useful, and had guidelines for getting started. It happens that many concepts behind good programming apply also to writing. Learning to write documentation may even make you a better programmer — because you may apply the empathy you learn through writing to ensuring that your code can be understood by the programmers who have to maintain and extend it.
This article consists of two sections. First, it applies some of the principles you have probably learned as a programmer to writing documentation. Second, it offers simple guidelines for starting the writing process.
Principles held in common
This section of the article organizes several bits of advice around general principles that apply to both programming and writing.
Do one thing well
The first lesson drummed into designers of mobile apps is to pick one task and hone their design till it accomplishes that task simply and elegantly. This advice echoes the original Unix philosophy: many small programs, each doing one thing well and communicating with other programs.
A technical document also should have one key goal. You may be trying to convey a good principle of programming or design, or to help your reader learn a skill such as how to use a project-specific API. There may be many steps toward this goal, but in describing each step, you need to make sure your description contributes to the initial goal you defined. The reader also needs to see how the concepts and steps you describe lead to the goal.
This very essay illustrates the same principle. My way of doing one thing well is to show you how to do one thing well. All the other points I make contribute to this message.
Modularize and refactor
Good programs are not only well-defined in their goals and actions, but are divided into well-defined subroutines or procedures with their own simple goals and actions. Documentation should also fall into sections that a reader can quickly take in, each section delivering a key idea.
Just as functions in a program call other functions, forming implicit trees, your text can refer to concepts defined in other sections. You can also point readers to other documents, taking advantage of other people’s best work in the same way your programs call functions from third-party libraries. Tracing dependencies between sections and documents is one of the most effective parts of writing, and is just as important as the ideas you write in each section.
If you find yourself describing the same concept or task repeatedly — a common discovery for people who write documents of more than trivial length — it’s time to extract that concept or task into its own section.
Sometimes you’ll find yourself reconsidering your conceptual framework. This commonly happens as software evolves and you have to update an old document. For instance, what used to be done with a series of commands may now be accomplished through a configuration file. The mental model for making an application using your library may change substantially.
In such circumstances, you should not feel constrained by the old organization of your document. You must reorganize sections around the new concepts and background your readers need, possibly raising the importance of some sections and lowering the importance of others. This process is similar to refactoring a program.
On the other hand, constant reorganizing or refactoring is wasteful. The process I describe at the end of this article will help you create a robust organization from the start and avoid reorganizing a document later.
Separation of concerns
Good programs hide complexities from higher-level functions. For instance, the knowledge of a file format can be limited to the functions that read and write the file. These functions are responsible for translating file contents into data structures that they expose to the rest of the program.
Documentation also falls naturally into different levels of complexity. Usually, internals and special hacks can be hidden from the reader. However, there will be subsets of readers that need to know these things to carry out particular tasks such as troubleshooting or hooking up external programs.
Therefore, try to isolate the complexities in your documentation. Don’t let complex terms and concepts leak into the easier sections that you show inexperienced readers. Introduce a new term only when the reader needs to know it, and link the information clearly to the task for which it is required.
Many documents start with “terms and concepts” sections, which may be helpful, but which should not be gigantic and comprehensive. You can introduce the terms and concepts in tiers as you move through your document and encounter tasks that require the extra background.
Programming is to some extent an engineering endeavor. At various points you decide whether to create bigger code in order to save memory, insert redundant error checks in order to provide security in depth, and so on. Writing presents trade-offs as well.
For instance, can you expect your readers to possess certain background? It probably doesn’t hurt to provide some of that background or point them to another document that does so. Can you feel confident that readers remember a concept you introduced several chapters earlier? Perhaps you should summarize the concept again (or hyperlink it). At each point, you need to decide whether the redundancy is worthwhile. In some cases, going over the same idea in a different way may help readers grasp a difficult concept.
Another trade-off comes in the speed with which you introduce new concepts. Some readers may benefit by proceeding in baby steps, making minimal changes to working programs or configurations in order to make sure they get each concept. Other readers may be ready to leap into radically new ways of doing things. Pace is a variable that each author will have to control based on an assessment of the reader’s learning style: some readers benefit from seeing the same concept over and over again in slightly different contexts, while some can grasp the concept quickly and move on.
How to turn this advice into action
The blank screen is frightening to programmers and authors alike. Here is a simple process that may enable you to write what you need to say, or help a team write it. The process may help you overcome the technical expert’s paralyzing instinct to endlessly refine each sentence. The process may also help you develop empathy for the reader — the essential trait of a good author, and one that many authors struggle to find.
Leave the text editor closed for a moment. Instead, just step through the process you want to describe: creating a program, writing a configuration, manipulating a repository, or whatever. As you go through this activity, think of the background your reader will need to perform it. Does the reader need to know what some term means? How to format some input or interpret some output? How to set up authentication or other basic steps? These are all sub-tasks. As a programmer, you would leave yourself a stub for a function you will write later. As an author, you will make a note that you need to write a section covering the sub-task and point the reader to it. Naturally, any background in the document should come before the sections that require an understanding of that background.
You may even choose to create an outline, laying out a master plan for your article. This will allow you to sort information into the proper sections, and ensure that the section you are currently writing focuses on just the point it needs to get across to the reader.
In this way, the various sections of the document emerge along with the relationships between the sections. By keeping the main point in mind as you proceed, you make your document do one thing well. Modularity flows naturally from the process, terms and concepts fall into their proper places in the document, and trade-offs can be considered as they arise. You can take a break from writing and return later or pass the document off to collaborators, because the requirements for the document are explicit.
And best of all, hopefully, writing no longer has to feel like a chore.