This article explains how to document the API. Its intended audience are the Haiku developers who want to document their own classes, and also the members of the API Documentation team who want to brush up the documentation. The guidelines are synchronous with the Haiku Coding Guidelines, which means that the formal requirements are the same where applicable. If you find an inconsistency, it's usually a good idea to report this on the documentation team's mailing list.
This document is divided into three sections. Formal Requirements describes the demands that are made from the markup and spacing of the files. Doxygen Commands describes the subset of Doxygen commands the Haiku API documentation uses, and which commands are used in which situation. Writing Guidelines describes the required style and structure of the documentation. If you are a developer and you want to prepare the first version of the documentation for the API documentation team to go over, have a good look at the formal requirements and the Doxygen commands. In addition, have a quick glance at how to write member and class documentation, since you'll need to know which information is mandatory for the documentation. Aspiring members or members of the API documentation team should read the third section carefully, and should also check out some of the finished documentation to get a good grip on the actual tone, style and contents of the documentation.
This section describes formal requirements, such as location and naming of the files, the header blocks of files, what blocks of documentation look like and how to put delimiters to separate different 'blocks' in your source file.
Doxygen, the tool that we use to generate the marked up documentation, has an ingenious parser that is able to scan through both header and source files making it possible to document the API directly in the headers or the source. However, the Haiku project have decided not to put the documentation in either location, and opt for the third option Doxygen provides: to put the documentation into separate files.
headers/os
. In a similar vein, the root of the documentation files is at docs/user
. The subdirectory structure, or the division of kits, will also be replicated.dox
extension. So Something.h
becomes Something.dox
. Note the case!Every documentation file will begin with the header block. It's basically a copyright block, with a reference to the author(s) and against which revision the documentation was written.
/* * Copyright 2007-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Niels Sascha Reedijk, niels.reedijk@gmail.com * * Proofreaders: * Alan Smale, ajsmale@gmail.com * * Corresponds to: * headers/os/support/String.h rev 19731 * src/kits/support/String.cpp rev 19731 */
The example above has a few elements that you should take note of:
/*and
*/
Authors
, put three spaces after the delimiter.Authors:
, which is followed by lines with names and email addresses. The latter one is optional, but recommended. Each author is proceeded by two tabs after the asterisk.Proofreaders:
in case the file has been proofread.Corresponds to:
. Underneath there is a list of files and their svn revisions that the current documentation is known to correspond with.*/where the asterisk is aligned with the ones above it.
Blocks are the basic units of documentation for Doxygen. At first it will feel like overkill to use blocks, but realize that Doxygen was initially designed to operate on header and source files, and then the blocks of documentation would be before the definition or declaration of the methods, functions, etcetera. Doxygen is used to operating on blocks, and that's why we need to reproduce them in our dox
files.
Blocks should adhere to the following standards:
/*!and close with
*/
Example:
/*! \fn bool BList::AddItem(void *item) \brief Append an item to the list. \param item The item to add. \retval true The item was appended. \retval false Item was not appended, since resizing the list failed. \sa AddItem(void *item, int32 index) */
//!
, however, we won't use these except for group markers, which you can read more about in the next section.Many of the header files in the Haiku API just document one class or one group of functions. However, there be a time when you come across a more complex header and for the sake of clarity in your dox
file you want to mark the sections. Use the standard delimiter marker for this, which consists of five slashes, a space, the title of the section, a space and another five slashes. Like this: ///// Global Functions /////
.
It is possible that there is documentation for parts of the API that are not (yet) part of the public API. It could either be that the documentation is part of the public header file (usually hidden behind a namespace like BPrivate
), or it is part of a private header file.
In case you are in the situation where you need to store private API docs, you should put the entirety of the documentation in a conditional block, with the INTERNAL
identifier. You open the block with the command //! \cond INTERNAL
and end the block with the command //! \endcond INTERNAL
.
There are two different cases where you must or could use these blocks:
This section describes all the Doxygen commands that will be used in the Haiku API documentation. As a rule, Doxygen commands start with a backslash (\) and are followed by whitespace (such as a space or a newline), with the exception of group markers; this is discussed in more detail later on. The commands can be divided into several categories, which are described in the following subsections.
Most commands accept an argument. Arguments can be one of these three types:
Because our API documentation is not done in the source, nor in the headers, Doxygen needs to be helped with figuring out what the documentation in the different blocks actually are about. That's why the first line in a documentation block would be one of the following commands:
\class
<name> \fn
(function declaration) ::
, are to be added as well. Modifiers such as const
should be included.\var
(variable declaration) \typedef
(typedef declaration) typedef
keyword.\struct
<name> struct
indicated by name.\def
<name> #define
with the identifier name.\page
If you have a look at the output that Doxygen generates, you can see that there are recurring sections in the documentation. Documentation that belongs to a certain section should be placed after a command that marks the start of that section. All the commands take a paragraph as argument. A paragraph ends with an empty line, or with a command that marks a new section. Note that this list only shows the syntax of the commands. For the semantics, have a look at the next section on style. In member documentation you can use the following:
\brief
{brief description} \param
<parameter-name> {parameter description} \return
{description of the return value} \retval
has a more structured form.\retval
<value> {description} \see
{references} There are also a number of things that can be used in pages and member documentation. See the style section to find out the appropriate situations in which to use them.
\note
{text}\attention
{text}\warning
{text}\remarks
{text}Sometimes you might require certain text to have a special markup, to make words stand out, but also if you want to have example code within the documentation you'll need a special markup. Doxygen defines three types of commands. There are commands that work on single words, commands that work on longer phrases and commands that define blocks. Basically, the single letter commands are commands that work on a the next word. If you need to mark multiple words or sentences, use the HTML-style commands. Finally, for blocks of code or blocks of text that need to be in "typewriter" font, use the block commands. Have a look at the following listing:
\a
\b
.<b>
and <\b>
tags.Typewriter font
\c
for single words.<tt>
and <\tt>
for multiple words or phrases\verbatim
and \endverbatim
. Everything between these two commands will be put in a distinct block that stands out from the rest of the text.\code
and \endcode
do the same, but Doxygen will parse the contents and try to mark up the code to make it look a little bit nicer.\e
for single words.<em>
and <\em>
for phrases.Pages are a very special element of the documentation. They are not associated with any kind of module, such as files or classes, and therefore, since they're not members, some of the structuring commands won't work. Important to know is that a page is the complete length of the block, so dividing it up in subsections by starting new blocks will not work. Instead, Doxygen provides some commands to structure text on a page.
First of all, you define a new page by using the \page
command. This command takes two arguments: a <name>
and (a title)
. The name is the internal identifier that can be used in linking between pages (see Miscellaneous Commands for \ref
). After you've defined the block to be a page, you can start writing the contents.
For more complicated pages, you might want to divide the page up in sections. Use the \section
command to define a new section. It takes the same arguments as \page
, namely the <name>
and the (title)
. If you need a deeper hierarchy you may use \subsection
and \subsubsection
, again, both with the same syntax. If you need to distinguish between sections in sub-sub-sections, you are able to use \paragraph
, which takes the same arguments.
If you are creating multiple pages that are related, you will be able to structure them in a tree by using the \subpage
command. This will rank the different pages in a tree structure. It will put a link in the place of the command, so you should place it at the top of the parent place and use it as an index.
Doxygen makes it possible to group certain members together. It is used in the BString class for example, where the members are grouped by what kind of operation they perform, such as appending, finding, etc. Defining groups is currently not as powerful as it could be, but if you use it inside classes, you will be fine if you follow the instructions presented in this section.
\ingroup
command.Groups of members are preceded by a block that describes what the group is about. You are required to give each group of members at least a name. Have a look at the example:
/*! \name Appending Methods These methods append things to the object. */ //! \@{ ... methods ... //! \@}
The block preceding the block opening marker, //! @{
, contains a \name
command and a paragraph that gives a description. The header block can be as long or short as you want, but please don't make it too long. See the Writing Guidelines section on how to effectively write group headers. The members that you want to belong to the group are between the group opening and closing markers.
\brief
description.There are some commands that don't fit into the categories above, but that you will end up using every now and then. This section will describe those commands.
The first one is \n
. This command sort of belongs to the category of markup commands. It basically forces a newline. Because Doxygen parses paragraphs as a single contiguous entity, it's not possible to mark up the text using carriage returns in the documentation. \n
forces a newline in the output. So in HTML it will be translated into a <br\>
.
Sometimes there are some parts of the API that you don't want to be visible. Since Doxygen extracts all the public and protected members from a class, and virtually every member from a file, you might want to force it to hide certain things. If so, use the \internal
command. If you place this just after the block marker, the command will be hidden from documentation. Any further documentation or remarks you put inside the block will not be visible in the final documentation.
Images can be a valuable addition to documentation. To include ones you made, use the \image
command. It has the following prototype: \image <format> <file>
. The format is currently fixed at html
. The file refers to the filename relative to the location of the documentation file. Any images you want to add should be in the same location as the dox file, so only the file name will suffice.
Modules are defined in the main book, and you can add classes to them by using the \ingroup
command. This commands adds the class to the module and groups it on a separate page. At this moment, the group handling has yet to be finalized. For now, add the classes to the kit they belong in. In the future this might change.
Finally, it is a good idea to link between parts of the documentation. There are two commands for that. The first one is \ref
, which enable you to refer to pages, sections, etc. that you created yourself. The second one is \link
which refers to members. The first one takes one word as an argument, the name of the section, and it inserts a link with the text of the title. \link
is more complex. It should always be accompanied by \endlink
. The first word between the two commands is the object that is referred to, and the rest is the link text.
This final section will present guidelines for the actual writing of the documentation. Both the structure of the documentation, which sections to use when, and the style of the writing will be discussed. Before diverging into the requirements for file and class descriptions, member descriptions and pages, there are some general remarks that apply to all types of documentation.
First of all, everything you write should be in proper English sentences. Spelling, grammar, punctuation, make sure you adhere to the standards. It also means the following:
Throughout the documentation you might want to provide hints, warnings or remarks that might interrupt the flow of the text, or that need to visually stand out from the rest. Doxygen provides commands for paragraphs that display remarks, warnings, notes and points of attention. You can use these commands in case you meet one or more of the following requirements:
This listing shows which one to use for which situation:
\attention
\warning
\note
\remarks
The design of Doxygen makes it very file oriented, and this might come off as inconvenient. At the moment, how to actually group the documentation is still under debate, but it does not change the requirement that a header needs to be documented before the members of that header can be documented. As such, the first documentation block in your dox
file will be the block that describes the header. Examples:
/*! \file String.h \brief Defines the BString class and global operators and functions for handling strings. */ /*! \file SupportDefs.h \brief Defines basic types and definitions for the Haiku API. */
The first statement defines what the block is about, namely the header file. The second element is the \brief
remark on what it contains. The first file defines the BString class and some global operators. You can see that reflected in the description. SupportDefs.h does not define classes, but rather a range of different functions and defines, so the text refers to that.
Classes are the basic building blocks in the Haiku API and as such have extensive documentation. This section will go over the actual class description. This section will present a list of items you should think about when writing the class description. This doesn't mean you'll have to include every item, it merely serves as a guiding principle that helps organise your thoughts. Have a look at the list:
\brief
description is obligatory. This description describes what it is. For example, BDataIO: "Abstract interface for objects that
provide read and write access to data." Note that this description is not a full sentence, but it does end with a period.When documenting classes, don't be too exhaustive. Avoid becoming a tutorial or a complete guide. This documentation is for reference only. If you want to enlighten the reader on bigger subjects, consider writing a separate documentation page that connects the different points you want to make.
Also, you don't have to put in any groupings of members in class descriptions. If you want to do that, physically divide the members up in groups. Look at the Member Grouping Commands for the actual commands, and at Groups for help on writing group headers.
Members and functions share the same basic Doxygen syntax, and they can be documented in a similar way. That's why this section deals with them together. Documenting members is probably the main thing you'll do when writing the actual documentation. There are some guidelines as to how, but the actual implementation probably differs per class. Keep the following points in mind:
\fn
line. This line needs to match the declaration, which is in the source file. This means that for members, also the class name and the scope indicator (::) should be present. Also note that this line doesn't have to adhere to the 80 column width limit.\brief
command. Give a short and clear description. The description starts with a capital letter and ends with a dot. Don't write the description saying what the method does, like "Starts the timer", but rather as what it will do: "Start the
timer."\param
command for that. For the description, use a short phrase such as "The
offset (zero based) where to begin the move." Note the capital and the dot.\retval
. You'll use this one when the return type is a bool or a status_t. In case of something else, use \return
. You can also combine these two. For example, a method that returns a length (positive) or an error code (negative).\see
if you have any references to other methods, classes or global functions. At least document all the overloaded methods. Also add methods that do the opposite of this method, or methods that are intimately related.In case of overloaded members, you'll need to make a decision. If you need to copy too much information, you might resort to putting it in one paragraph with the text "This is an overloaded member function, and differs from <name> only by the type of parameter it takes." That will keep the copying down and will point developers right to the place where they can get more documentation.
Again, like class descriptions, you'll have to find a good middle-ground between too much information, and too little. Again, write for the broadest audience possible, and resort to notes and warnings for specialised audiences.
This section helps you document (member) variables and defines that define constants, as well as enumerations and their values. If you need to document a #define
macro that takes arguments, have a look at Members and Functions
The \brief
description of all these types follow a similar structure. They are a short phrase that mention what the variable contains. Example:
/*! \var char* BString::fPrivateData \brief BString's storage for data. This member is deprecated and might even become \c private in future releases. If you are planning to derive from this object and you want to manipulate the raw string data, please have a look at LockBuffer() and UnlockBuffer(). */
The variables you are going to encounter are either public
or protected
member variables, or global variables that have a certain significance. In the case of member variables, you'll need to document what they mean and how the developer should manipulate them. If the class is one that is meant to be derived from, make sure that in the description of the variable you mention how it interacts with the others, and how the developer should make sure that the internal coherence of the data and code members of the inherited class is maintained.
Global variables will mostly be constants. If so, document what they stand for and what they might be used for, as well as which classes and functions depend on that constant. If the variable is meant to be changed by the developer, explain what values are valid and which functions and classes depend on this variable.
Defines are usually used as message constants. Give a short description of what the message constant stands for, and where it might be sent from and where it might be received.
Enumerations can either be anonymous or named. In case of the latter, you can give a description of the enumeration in a documentation block that starts with an \enum
command, followed by the name of the enumeration. If the enumeration is within the scope of a class, prepend the classname and the scope indicator. In case of an anonymous enum, you can only document the individual members (which you should do for the named enumerations as well), which can be done within code blocks that start with the \var
command. Doxygen will know that it's an enumeration value, don't worry about mixups. If the enumeration value is within a class, prepend the classname and scope indicator. Give a short description of the value, which methods react to it, where it might be used, etcetera. Don't go as far as to copy information too much. For example, if you use an enumeration in only one class and you document the possible values there, then don't do that again for the enumeration documentation: rather just refer to it. That sort of documentation belongs to the class description, not to the enumeration.
If you subdivide members of classes into groups, you have the ability to apply some general information that will be listed above the listing of the members in that group. See the section Member Grouping Commands on how to define groups. This section is on what to put in the header block.
First of all, it's probably a good idea to give your group a name. This name will be printed as a title and will enhance the clarity of what the group contains. If you put the \name
command as the first command of a group, the rest of the words on that line will be used as the title. You should choose simple titles of no more than three words.
It's possible to add one or two paragraphs of information. These paragraphs should contain some quick notes on which of the members in that group to use for what purpose. See it as a quick subdivision that a developer could use as a guide to see which method he actually wants to use. Don't go on describing the methods in detail though, that's what the member documentation is about. Have a look at the example:
/*! \name Comparison Methods There are two different comparison methods. First of all there is the whole range of operators that return a boolean value, secondly there are methods that return an integer value, both case sensitive and case insensitive. There are also global comparison operators and global compare functions. You might need these in case you have a sort routine that takes a generic comparison function, such as BList::SortItems(). See the String.h documentation file to see the specifics, as they are basically the same as implemented in this class. */
Straight, to the point, gives no more information than necessary. Divides the members up into two groups and refers to other functions the developer might be looking for. The hard limit is two (short) paragraphs. Using more will not improve clarity.