Documentation
Good documentation means new team members have a complete set of resources, and can more easily approach the code. Good documentation also means we can keep a high-level outlook on the organization of our code base, and reminds us of our goals for particular constructs, months after we wrote them originally. It's an all-around good thing. In fact, if there is a golden rule for documentation, it is when in doubt, write more comments. We can always revise this.
As an additional consideration, realize that extended comments should only be necessary where the correct naming of a routine or data structure does not fully represent its behavior. The goal of good code design is that comments need only supplement the information given by good naming schemes and logical design. Look out for common "code smells" like comments being longer than the function itself. Longer functions are also harder to document; keep the functions around 30 lines where it is practical, and the documentation should come easily.
The Doxygen Tool
We will be using Doxygen to document our code, and have adhered to its syntax throughout the guide below. The end-goal is to incorporate documentation into the general build system, so that in addition to creating executable binaries, we will also have complete html documentation for the project. While writing your documentation comments, feel free to make use of and refer to the Online Manual, in addition to the templates for this project below. You may find the reference on Special Commands especially helpful.
1. Documentation Format for Doxygen
Documentation comments for C, C++ or compatible languages should be written in C-style block comments as below. Comments in other languages should follow this example with a leading documentation mark (frequently #!) followed by a line of comment marks along the left margin. Tabs should not be used in documentation comments, as nothing need be indented save for separation from the block itself.
/*! * \command followed by its arguments * * Free-standing paragraphs are always separated by blank lines. * * One space separates every line from its leading * marker. Nothing should be on the line with /*!. */
2. C Documentation
- All files should begin with a \file comment block, describing the contents of the file.
Because C does not offer the benefit of abstraction in classes, files become this abstraction. Both implementation (.c) and header (.h) files should include this block, but the implementation header should be very short and refer back to the .h file by mentioning it explicitly. Doxygen will automatically turn this into a link.
Tags in this comment must always include: \file, \brief, and \author (there may be more than one author).
Example: motion_planner.h
/*! * \file motion_planner.h * \brief Definitions for routines used to decide on a motion plan for the car * based on sensory input. * * An extended description of the scope of these routines is contained here. * Avoid repeating information about the routines themselves; that will be * covered in the routines' own documentation. Relevant information * includes: * - Scope of these routines (what do these functions intentionally *not* * do?) * - Intended use, cautions of intent (e.g. "These routines are not good for * graphics.") * - By the way, this makes a bulleted list. * * As always don't write anything that isn't relevant and necessary. Be * concise. Oh, and write your name below... * * \author Andres J. Tack (atack2@uiuc.edu) * \author A Random Assortment of Fuzzy Animals */ ...
Example: motion_planner.c
/*! * \file motion_planner.c * \brief Implementation for routines from motion_planner.h. * * \author Andres J. Tack (atack2@uiuc.edu) * \author Joe P. Contributor (jpc@gmail.com) */ ...
- Structures should be documented where they are first defined, and every field should be documented individually.
Spaces should be used to align field documentation wherever possible.
Tags in this comment must always include: \brief
Example: occupancy_grid.h
... /*! * /brief Write one sentence about what the occupancy grid structure is or what * it enables. * * Add cogent thoughts about the designs and intentions of the structure in their * own free-standing paragraphs. */ struct OccupancyGrid { int width; /*!< Width (in "tiles") of the grid. */ int height; /*!< Height (in "tiles") of the grid. */ uint8_t** tiles; /*!< Two-dimensional array of tiles, where this long line is brought down below. */ }; ...
- Functions/routines should be documented in the header (.h) file, and not in the implementation (.c) file.
While it is good to have documentation wherever someone is reading (which tends to be the .c file more frequently for the author), it is generally bad to duplicate anything in two places. We comment the header file because it is the entry point for most users, and thus it is the most relevant place. See the examples below for correct function documentation syntax. Note that parameters and return values must be documented for clarity.
The exception to this rule is static routines defined only in a .c file. These should be documented where they are implemented. The main() function, for example, should have its own documentation comment in the file main.c, even if there is a main.h used for #define directives.
Example: motion_planner.h"
... /*! * \brief Allocates space for a motion planner object with an occupancy grid of the given * dimensions. * * All sub-structures, including the occupancy grid, are allocated and initialized for * the user, ready to use. * * \param width is the width in tiles of the internal occupancy grid. * \param height is the height in tiles of the internal occupancy grid. * * \return a ready-to-use MotionPlanner object with a blank occupancy grid. */ struct MotionPlanner motion_planner_init(int width, int height); ...
2. C++ Documentation
- Header (.hxx) files which declare classes should begin with a \class documentation comment describing the class therein.
It follows from this that only one root-level class should appear in any one file, and this class should appear without helper methods in the .hxx file. This comment should appear absolutely first thing in the file, before #includes and forward declarations, and should be immediately succeeded by the #ifndef guard.
Tags in this comment must always include: \class, \brief, and \author (there may be more than one author).
Example: coord.hxx
/*! * \class Coord * \brief An X,Y coordinate pair which supports manhattan arithmetic. * * By manhattan arithmetic, we mean that the length of the path from * one point to another is a sum of the differences in each of X and Y. * * \author Andres J. Tack */ #ifndef __COORD_HXX__ #define __COORD_HXX__ ...
- Implementation (.cxx) files for classes with an associated (.hxx) file should not include any documentation of the file; the purpose of the file is implicit.
- All files not part of class definitions should include their own \file documentation.
This should be a limited set of files, but virtually all files defining a main() function apply here. Header files including no class should be likewise documented.
Example: test_client.cxx
/*! * \file test_coord.cxx * \brief Runs unit tests for the Coord class. * * To build these tests, use the 'unit' target of the makefile by typing: * make unit * * The test may then be run with the global testUnits.py script in the root of the trunk. * * \author Andres J. Tack (atack2@uiuc.edu) * \author Joe P. Contributor (jpc@gmail.com) */ ...
- Class methods should each have associated documentation, written once in the header (.hxx) file.
This includes constructors. In this comment, it is especially important to document exceptional cases for the function. For example, if a function returns a NULL pointer on failure, this should be noted in the \return section.
Tags in this comment must always include: \brief, \param (one for each parameter), and \return (unless the return value is void).
Example: coord.hxx
class Coord { public: ... /*! * \brief Tests whether this coordinate is within the area * bounded by the two given corners. * * \param topLeft is the top-left corner of the bounding box. * \param bottomRight is the bottom-right corner of the bounding box. * * \return true if this point exists completely within the bounding * box. false otherwise. */ bool isInside(Coord &topLeft, Coord &bottomRight); ... };
- Public variables should always be commented. Whenever possible, they should also be grouped.
Variables that come in pairs or triples are excellent choices for grouping. In the case where variables are grouped, it is also good practice (though not always necessary) to then briefly comment the group members individually.
Tags in these comments must always include: \brief. If a group is declared, it must also include the \name tag.
Example: gnome_food.hxx
class GnomeFood { ... private: /*! * \brief Describes whether a gnome is currently chasing after this * tasty morsel. */ bool myIsBeingHunted; ... };
Example: coord.hxx (grouped public variables)
class Coord { public: /*! * \name Coordinate Pair * \brief The x and y of the (x,y) coordinate pair. */ //@{ int x; /*!< The horizontal component. */ int y; /*!< The vertical component. */ //@} ... };
3. Python Documentation
This section is currently unclear to me. E-mail Tack if you have suggestions. Otherwise, it will be written soon.
