Documentation Team/API Documentation

< Documentation Team
Revision as of 12:58, 28 June 2008 by Dfarning (talk | contribs) (DevelopmentTeam/Tutorials/API Documentation moved to DocumentationTeam/API Documentation: API documentation is significant enough to warrant a place in the doc team root.)
Pencil.png NOTICE:  This page is a draft in active flux...
Please contribute to these contents and discuss issues on the discussion page.


Definition

API (Application Programming Interface) documentation is documentation that applies to a program and its interfaces. It is documentation that explains to a developer who is going to work with the program, or a developer who is going to work on a program, how things work and what methods are there to call.

API documentation is sometimes called an API reference manual. It needn't just be a reference manual, though, there can be extensive additional material, like tutorials, histories, etc. In this page, we will refer to all the material that documents and explains the API of a piece of code as "apidox."

Good apidox take some effort to write -- but less effort than good user documentation, since you as a developer are writing for another developer, and explaining how code works and what it is supposed to do. So your audience is clear to start with. The benefits of apidox come when someone else (or maybe even you several months later) needs to (re)use the code, or extend it. Good apidox means that someone new can show up, understand your code, and produce meaningful patches (that is, help) all the more quickly. Especially for libraries, good apidox make the library usable as a black box (and that's how they should be) because all the needed documentation is available in the apidox and not hidden in the (perhaps inaccessible) code.

Preamble

APIDOX are what make a program accessible to other contributors. They are not essential, but they certainly help a great deal for new people who want to work on your code, or better yet, re-use it elsewhere with a minimum of modification.

Look at the KDE documentation to get a feeling of what good apidox look like. There is a consistency of style, a thoroughness which permeates all the documentation. It is possible to learn a lot about KDE just from reading the documentation. You do not necessarily need to run the tutorial programs or read the source code of the library to find out what a parameter flags does in some method of the library. It is all spelled out for you.

Writing apidox is a two-part process. One part is technical: you need to understand the code you are documenting -- or at least know what it is supposed to do and how it is meant to be used. The other part is plain discipline: apidox are most useful when they are exhaustive.

This document is going to try to prevent the apidox process from becoming exhausting, by giving straightforward tips about how to write apidox.

APIDOX Basics

APIDOX are generated by the Doxygen documentation tool. This tool reads the source code for your application (or library) and produces nicely formatted documentation from it. There is a good reference manual available -- but let's hope to make it unnecessary to read, for basic use anyway.

You don't even need to have Doxygen installed to work on apidox for your application. Every few hours, api.sugarlabs.org compiles apidox for all of the Sugar modules we know about. Logfiles are kept and you can see your apidox on the site, or read the error messages and fix those. ...it might not be the fastest way to write and fix apidox, but it gets the job done, and if you spend just an hour at the end of the day writing some apidox, it's sufficiently useful.

Basic apidox are fun and simple: you write comments in your code explaining what things are supposed to be for. These comments are nearly indistinguishable from stuff you would be writing in the headers of your code anyway, so that's not hard to do.

APIDOX consist of two types of comments python docstrings and doxygen directives. These docstrings are surrounded by """ (quote, quote, quote) -- that's what makes them special. The rest of the content of the comment is just plain text describing a part of your program. The plain text is interpreted by the Doxygen processor, so that you can write accurate descriptions of parameters, return types, and do some basic text markup.

Doxygen directives are one line comments preceded by a #. They are short statments that help Doxygen determine the organization of your package.

But documentation can be very straightforward: just write down what a method does, surrounded by """ and """, like this:

 """
 This method increases the IQ of end users.  Therefore, it
 should be called whenever possible (i.e. instead of having
 idle time, you might think of calling this method.)  You might
 even insert it into your own event loop to ensure it is called
 as often as possible. If these calls decrease the number of
 new features, it's still no problem to call it. 
 """
 def increaseIQ (IQ):

Note: This process is slightly different from the instruction on the Doxygen site. Standard Doxygen comments are surrounded by /** and */. In order to maintain compatibility with standard python documentation, api.sugarlabs.org runs a preprocessor that converts docstrings into doxygen comments.

For proper apidox, you need to document every "thing" in your program. "Things" here are: sugar modules, python packages, python modules, classes, functions, and variables. Complete apidox looks something like this:

 # \file example.py
 # \brief An example Python program.
 
 # Demo class
 class Demo:
   """
   \brief A demo class, it's really just for demonstration.
   The detailed description of the class would appear right here.
   However, as this class is utterly useless when talking about its
   functionality it actually has no detailed description which is
   sort of a pity, since a couple of lines of documentation would
   make it look like a real documentation. But as this is just an
   example of how the doxygen output might look like a one-liner has
   to be enough. Insert your documentation here as appropriate. You
   get the idea now, don't you? If not, I can't help it but I
   certainly won't type in a lot of nonsense just to make it look \em
   real.  No, definitely not.
   """
   def __init__(self):
       """The constructor."""
   def foo(self, bar):
       """
       The infamous foo method.
       There's no detailed description necessary for the \em foo()
       function as everybody know what it does.
       \param bar The \a bar argument is compulsory, never leave it out.
       \return The \a bar input after processing by the \em foo() function.
       """
       pass
   ## protected:
   def spam(self, amount):
       """
       Return an amount of spam.
       \param amount (\c int) The amount of spam.
       \return An amount of spam.
       """
       return amount*"spam"
 # Another demo class
 class AnotherDemo(Demo):
   """\brief This class is derived from the demo class."""
   def __init__(self):
       pass

You can see here that each nesting level of "things" is documented with a comment -- the module, the class and the method. Things that are private do not need apidox.

It is important to document each level of nesting, because if you leave one level out, Doxygen will ignore the documentation in inner nesting levels, and you will be left wondering where it has gone. For instance, if we leave out the class documentation, then the method documentation will vanish as well. This is one of the common pitfalls to writing apidox.

If you just do this -- write an explanation for every part of your program -- then you're already a long way on the road to having complete apidox. Writing all those explanations makes your program more accessible to other developers -- and often shows you where the design or choice of names is sub-optimal. So it's a win for you both ways.

You can consult the list of supported tags for examples of more fancy apidox -- explaining parameters, for instance, and annotating the apidox with credits and examples. It's also worthwhile to take a look at the section on enabling apidox, but it's also fine to divide the work: you write the apidox themselves, and ask me (mailto:dfarning@sugarlabs.org) to enable apidox generation for your module. And I will.

Writing APIDOX in New Code

The following little checklist should get you through the worst of writing apidox.

1. Write apidox as you code.

The discipline it takes to write down the apidox for function foo() now as you are thinking of foo() and what it needs to do more than compensates the effort later where you have to remember what foo() was supposed to do, anyway.

This isn't to say you have to do it this way, but it is convenient. The apidox also document design decisions. They also document what you want a particular piece of code to do, regardless of what it actually does. That makes it possible to independently check that the code does what it's supposed to: because it's written down.

2. Document your packages completely

Packages are what's most visible to users (in this context, users are developers who are re-using) of your code, and they should be complete. Document each structural bit of the package as you go along. This means:

  • Every package should have a package comment.

In the root directory of your packages create a file named Mainpage.dox. The first line of the comment must be the @mainpage doxygen directive followed by your package name. Next is the package comment wrapped in a docstring. Last are some apidox variables which help define the menu structure.

 # @mainpage Sugar 
 """
 Here is the description of the package named sugar.
 """
 //DOXYGEN_SET_PROJECT_NAME=Sugar
 //DOXYGEN_NAME=Sugar-module
 //DOXYGEN_EXCLUDE 

  • Every module should have a module comment.

A given module only needs a comment once in your source tree (or within one bunch of files that generate apidox together). Near the top of each module __init__.py file, create a @mainpage <module_name> directive followed by a description of what the module is for and what it defines. Wrap this up in docstring.

 """
 @mainpage Control Panel
 Here is a description of the module named controlPanel.
 """

  • Every class should have a comment. Classes are the important building blocks of your application or library, so this is one place where writing lots helps. Write down why the class exists. Write down what it is supposed to do. Give an example of how to use it. Explain how not to use it, or what prerequisites it has (for instance, lots of classes need a KInstance object, but don't document that explicitly).
    The same caveats apply as with namespace apidox: make sure the class follows its apidox immediately.
  • Every method should have a comment explaining what it does and what the parameters are for. Method parameters should be documented using @param. Don't rely on the name of the method or the parameters to be fully self-documenting. Besides, writing these things down properly will trigger Doxygen errors if you change them in an incompatible way later -- and that is going to save you lots of time in finding source and binary incompatibilities and explaining to users why their code suddenly doesn't do what they expect (assuming it compiles at all). So good method apidox is an additional insurance against making bad changes. Same caveats apply.


3. Watch this space!

Watch api.sugarlabs.org for the results of your apidox work. Check the log files for errors -- Doxygen can complain quite loudly.

4. Write a main page for your application.

This is usually done in a separate file Template:Path in the top-level of a library or application. The file's content is just a single apidox comment that starts with /** @mainpage title ; the rest of the file is just a long comment about what the library or application is for.

Fixing APIDOX in Old Code