Writing Documentation

It is our firm belief that software can only be successful if it is properly documented. Too many academic software projects die prematurely once their creators leave the university or the workgroup in which the software was developed, since with their creators also knowledge of internal structures, interfaces, and the valuable bag of tricks leaves, a gap that can not be closed by reading sources, trial-and-error, and guessing.

The deal.II project has therefore from its infancy adopted a policy that every aspect of the interface needs to be well-documented before its inclusion into the source tree. Since we have found that it is impossible to keep documentation up-to-date if it is not written directly into the program code, we write the documentation directly at the place of declaration of a function or class and use automatic tools to extract this information from the files and process it into HTML for our web-pages, or LaTeX for printing.

In addition to the API documentation, we maintain a series of well-documented example programs, which also follow a certain ``literate programming'' style in that the explanations of what is happening are integrated into the program source by means of comments, and are extracted by small scripts.

This document first explains the basics of documenting the API and then of writing example programs.

Writing API documentation

In order to extract documentation from the header files of the project, we use doxygen. It requires that documentation is written in a form which closely follows the JavaDoc standard.

Basic layout of documentation

Basically, every declaration, whether class or member function/variable declaration, global function or namespace, may be preceded by a comment of the following form:

/**
 * This is an example documentation.
 */
class TestClass
{
  public:
           /**
            * Constructor
            */
    TestClass ();

           /**
            * Example function
            */
    virtual void test () const = 0;

           /**
            * Member variable
            */
    const unsigned int abc;
};

doxygen will then generate a page for the class TestClass and document each of the member functions and variables.

Extended Layout

In order to allow better structured output for long comments, doxygen supports a great number of tags for enumerations, sectioning, markup, and other fields. We encourage you to take a look at the doxygen webpage to get an overview. However, here is a brief summary of the most often used features:

Code examples for the usage of single classes

Writing example files for classes is supported by doxygen. These example files go into deal.II/examples/doxygen. If they are short, documentation should be inside and they are included into the documentation with @include filename. Take a look how the class BlockMatrixArray does this.

Larger example files should be documented using the doxygen command @dotinclude and related commands. However, if these programs do something reasonable and do not only demonstrate a single topic, you should consider converting them to a complete example program in the step-XX series.

Writing example programs for the tutorial

Tutorial programs consist of an introduction, a well documented code, and a section that shows the output and numerical results of running the program. These three parts are written in separate files: for the step-xx program, for example, they would be in the files examples/doc/step-xx/doc/intro.dox, examples/doc/step-xx/step-xx.cc and examples/doc/step-xx/doc/results.dox. There are a number of scripts that then process and concatenate these three different files and send them through doxygen for generation of HTML output. In general, if you want to see how certain markup features can be used, it is worthwhile looking at the existing tutorial program pages and the files they are generated from.

The introduction

The introduction, as well as the results section, will be processed as if they were doxygen comments. In other words, all the usual doxygen markup will work in these sections, including latex formulas, though the format for the formula environment is a bit awkward. Since it takes much longer to run doxygen for all of deal.II than to run latex, most of the lengthier introductions are just written in latex (with a minimal amount of markup) and later converted into doxygen format. One thing to be aware of is that you can reference formulas in doxygen, so you have to work around that using text rather than formula numbers.

More important is what goes into the introduction. Typically, this would first be a statement of the problem that we want to solve. Take a look, for example, at the step-22 or step-31 tutorial programs. Then come a few sections in which we would discuss in mathematical terms the algorithms that we want to use; this could, for example, include the time stepping, discretization, or solver approaches. step-22 and step-31 are again good, if lengthy, examples for this.

On the other hand, if a program is an extension of a previous program, these things need not be repeated: you would just reference the previous program. For example, step-16 does not talk about adaptive meshes any more — it extends step-6 and simply refers there for details. Likewise, step-32 simply refers to step-31 for the problem statement and basic algorithm and simply focuses on those parts that are new compared to step-31.

The purpose of the introduction is to explain what the program is doing. It should set the mindset so that when you read through the code you already know why we are doing something. You may not yet know how this done, but this is what the documentation within the code is doing. At least you don't have to wonder any more why we are building up this complicated preconditioner — we've already discussed this in the introduction.

If it helps the understanding, the introduction can refer to particular pieces of code (but doesn't have to). For example, the introduction to step-20 has pretty lengthy code snippets that explain how to implement a general interface of operators that may or may not be matrices. This would be awkward to do within the code since in the code the view is somewhat smaller (you have to have complete parameter lists, follow the syntax of the programming language, etc, all of which obscures the things one wants to discuss when giving a broad overview related to particular C++ constructs). On the other hand, showing code snippets in the introduction risks duplicating code in two places, which will eventually get out of synch. Consequently, this instrument should only be used sparingly.

The actual code

At present, the tools that extract information from the actual example programs code are rather dumb. They are, to be precise, three Perl scripts located in the directory of the deal.II/doc/doxygen/tutorial tree, where the .cc files of the tutorial programs are converted into doxygen input files. In essence, what these scripts do is to create doxygen input that contains the comments of the program as text, and the actual code of the programs as code snippets. You can see this when you look at the pages for each of the tutorials where the code is indented relative to the text.

The whole thing being interpreted by doxygen means that you can put anything doxygen understands into comments. This includes, for example references to classes or members in the library (in fact, you just need to write their name out and doxygen will automatically link them), formulas, lists, etc. It all will come out as if you had written comments for doxygen in the first place.

The bigger question is how to write the comments that explain what's going on in individual code blocks. Many years back we wrote them so that every line or every two lines had their own comment. You can still see this in some of the older tutorial programs, though many of them have in the meantime been converted to a newer style: it turns out that if you have comments so frequently, it becomes hard to follow the flow of an algorithm. In essence, you know exactly what each line does, but you can't get an overview of what the function as a whole does. But that's exactly the point of the tutorial programs, of course!

So the way we now believe tutorial programs should be written is to have comments for each logical block. For example, the solve() function in many of the programs is relatively straightforward and has at most a dozen lines of code. So put a comment in front of the function that explains all the things that are going on in the function, and then show the function without comments in it — this way, a reader will read through the half or full page of documentation understanding the big picture, and can then see the whole function all at once on a single screen without having to scroll up and down. In the old way, the code would be spread out over a couple pages, with comments between almost any two lines, making it hard to see how it all fits together.

It is somewhat subjective how much code you should leave in each block that you document separately. It might be a single line if something really important and difficult happens there, but most of the time it's probably more along the lines of 6 to 12 lines — a small enough part of the code so that it's easy enough to grasp by looking at it all at once, but large enough that it contributes a significant part or all of an algorithm.

The results section

The results section should show (some of) the output of a program, such as the console output and/or a visualization of graphical output. It should also contain a brief discussion of this output. It is intended to demonstrate what the program does, so that a reader can see what happens if the program were executed without actually running it. It helps to show a few nice graphics there.

This section needs not be overly comprehensive. If the program is the implementation of a method that's discussed in an accompanying paper, it's entirely ok to say "for further numerical results, see ...".

Like the introduction, the results section file is copied verbatim into input for doxygen, so all doxygen markup is possible there.


Valid HTML 4.01! Valid CSS!