Arnt Gulbrandsen
About meAbout this blog

Writing class documentation

A mere ten years after I promised to write this: here's a post describing how to write decent class documentation, for programmers, not writers. This describes how I wrote class documentation for Qt.

This has four parts: Write a sentence-long blurb with the most important thing you can say about the class. Write a few more sentences to give a complete, but rough overview of what the class is (is, not does). Make a list of methods, member variables, enum values and other subordinates of the class, sort the list into aspects, then write about each aspect (but not each member). Finally, make zero or more examples.

Good writers will do it differently, but the goal here is to write something good, not to be a good writer. The best is the enemy of the good.

You don't want to ship crap, and you also don't want to set the requirements so high that only some mythical other people could do the job. So let me digress first into what good means.

Good means that it helps the reader understand your class and how to use it for the reader's purpose. You don't know what that purpose is, but you can guess fairly well, because you are a software developer and familiar with the subject. If anyone can guess well, then it's you.

Sometimes the reader is someone on your own team, working on the same software. In that case the reader will be used to reading and editing the source code. In other cases you're supplying a black box that most readers will use via rubygems, maven/gradle, go get or similar repositories. Those readers never see the source code, they never see the unit tests. When you describe a class in five words or fifty, the description you choose often depends on who you are talking to. That is, the meaning of good depends on the audience.

Both variants of good are well within your capability as a software developer, though. You've done both things verbally, probably many, many times, and you succeeded at getting the point across. Doing it in writing isn't much more difficult.

Back to writing good class documentation:

Parts 1+2: The thirty-second description that'll tell people what this class really is. As for documenting functions, doing this helps you clarify your thinking. Writing a few sentences sentences to give an overview of what the class is improves your own overview.

The simple way to write this is to write a single sentence about the class. A single short sentence, it doesn't have to be complete, it should be simple, understandable and not wrong. Then you look at the sentence, think about what is important and left out, and write each important thing as a single sentence, or maybe as two. This writing style is called the inverted pyramid, and good journalists use it a great deal.

When you write this description, it's best to explain what the class is, rather than what it does. If your phrasing slides towards does, your result often becomes less valuable for the readers, who are focused on what their own code does. A function does, but a class is, and if you keep to is, your description tends to be readable for a wider range of readers with a wider range of use cases.

The detailed description of QWidget is a long example; read the first six paragraphs. The first sentence is the gist, after that each sentence or pair of sentence describes some additional important aspect. By the time you've read all six paragraphs you'll generally know whether QWidget is the class you need to inherit, or what the subclasses have in common.

QPushButton is a shorter example; only three lines of text are enough to describe what that is. The first sentence says what it is. A second, clarifying sentence introduces both of the names readers may have read before. It also suggests the kind of use case for which this is suited, because picking the wrong kind of button is such a common mistake. A third sentence names some good and common examples, in case the reader has used buttons but knows little terminology.

That's it. Three sentences, and the reader has a fair idea about whether this is the right class to use. QWidget needs a great deal more. Both things happen in practice. Most classes are well documented using a three-sentence description, some really need much more.

Of course, as you can see there are more sentences after the three. That's okay, it's not difficult to write, because those are sentences about the details, not about the class. I (or we?) wrote three sentences about this, two or three sentences about that, and both parts were simple because writing three sentences is much simpler than writing a long text.

Part 3: Filling in the right amount of details to tell people how to put this class to use.

The rest of the text about QPushButton is a sequence of short texts about some aspect of the class. We wrote those by making a list of enum values and member function, eliminating duplicates (e.g. accel()/ setAccel()) and sorting the result into a list of aspects. The enum ToggleType isn't an aspect of the class, for example, but the three values of that enum were used to make the list of aspects. Then we wrote approximately one paragraph per aspect, sometimes a little more.

The text looks a little blocky. A trained copy editor can easily see that each paragraph was written mostly on its own. On the other hand, a trained software developer can read this documentation and use the class well.

Part 4: Examples

After that, consider what examples the reader should see. Do not make the mistake we made in the early years of Trolltech, and write code that interests you. Our hello, world eventually morphed into an example of how to make colourful animated letters jump around the screen. Fine and impressive, but not helpful for a reader that looks for how to write a first hello, world.

What you should do is look at the documentation you've written, and if the class merits an example at all, you decide what example the reader would ask you for, and write that precise example.

QPushButton contains an excellent single-line example. (You may have noticed that even though it was written at the end, we moved it up to nearly the start of the text.)

QWidget is used by many example programs, so it contains a three-sentence description of one example program, explaining why that that particular example is good to start with.

QPushButton also contains automatically generated links to complete example programs that use it; our documentation tool (qdoc) generated those. In my opinion, each of those example programs should have a declared audience and goal. You should make clear (in a comment in each example program) both what this example program is supposed to teach and who should learn from it. We didn't at Trolltech, which harmed both the example programs and us as team.

After that: Editing helps. Editing, in this case, mostly means moving the blocks around. You can see that we moved the example in QPushButton near the top. That just looked right. Looking at QWidget, you can see that the events are grouped. I wrote the text for each group independently, then we looked at it and decided that the exposition worked best if the descriptions were ordered in that order.

Real editors do more, of course. This posting is about writing well enough to enable software developers to use a class well, not about writing better than that.

After that: Refining the documentation due to FAQs helps. When we answered support questions, when we answered FAQs, anything, we'd try to edit something a little to make that FAQ go away. That's why the QPushButton text points to the other kinds of buttons (people have terrible problems deciding whether a tool button, command button or radio button is the best for a given case, and so on), and it's why the QWidget text mentions top-level widgets so prominently.

This posting hardly mentions tools. Good documentation benefits from good tooling, but not all parts equally. The subject of this posting is text that has to come from a someone's mind. Other parts can come from analysing e.g. relationships in the source code.

Some tools aim at producing the best possible result from whatever effort you put in. That's not what I write about. My goal is strictly to produce usable results with as little human effort as possible.

The links above point to a very old version of Qt. Later versions are perhaps better documented, but for this posting I thought it suitable to use a version written by software developers rather than by technical writers. The users praised it. People like you can write documentation that users praise.

FAQ handling

FAQs happen, and have to be handled. There are four ways. A sorted commented list (I promise this won't be a rant):

Do nothing. A valued approach, and there is much to say in its favour. For an opensource hacker who's basically writing code to scratch his own itch (using the male pronoun seems safe in this context) there's no intrinsic reason to care about FAQs at all. […More…]

Use the source wisely, Luke

No matter what the documentation says, the source code is the ultimate truth, the best and most definitive and up-to-date documentation you're likely to find. Sounds really good. But grand sentences often sound really good — better than reality even. So let's try checking that against the concrete code and documentation I personally have written. Have I written anything where the documentation describes the code better than the code itself does?

Here's what I could think of during the time it took to brew myself a pot of tea:

I have written code that was not supposed to be used, except by internal unit tests. For instance to get January 1, 1970 instead of the current time. Very useful for unit tests, but do you really want to depend on that kind of thing?

I have written documentation that described only what's common to the current and the the next major version (in Qt, I did that many, many times). Anyone who depended on the documented behaviour got a simple upgrade, anyone who read the source might get trouble, often […More…]

Writing (mostly) to write

Most people who talk about literate programming seem to care mostly about the output. The written documentation. I care more about the actual writing, and the result of the writing process.

When you write something, when you explain it, you gain a deeper insight yourself. That's a cliché, to be sure, but it can be leveraged to write better code. There are two parts to it: Helping yourself and having your tool help you. […More…]