Gromacs

Comments In Code

    Table of contents
    1. 1. Proposal for Doxygen usage

    Version as of 01:16, 25 Aug 2019

    to this version.

    Return to Version archive.

    View current version

    In order to finally have a real development manual we need to automate the process of generating a cross-linked index of functions. doxygen can do that, but it requires special format comments in all the header files. It would also be good to check which functions are used only from their own C file, (i.e. test whether they can be made static).

    General guidelines for comments:

    • In general, spend time explaining WHY, not how. Explain the algorithm you use for your fancy new sort algorithm and provide a reference to it, rather than writing "go through all elements" before the for-loop. Most programmers will figure out the latter after a minute anyway :-)

    Some parts of the source already contain Doxygen comments (thread_mpi and selection libraries, and some nonbonded kernel stuff). Autoconf also generates an input file for Doxygen in the root of the tree, but the contents of the file could be improved by only specifying the necessary options.

    This project should start with deciding where we want different kinds of comments to appear. Points to consider:

    • What to document in the source, and what to document separately, e.g., in a wiki? For the high-level design, it could be easier to write the design on the wiki, and later use that as part of the documentation, so a line should be drawn somewhere on what belongs to the wiki and what belongs to the source code.
    • We probably want at least the brief description in the header files. How about other API documentation like longer descriptions and parameter lists? In the header files or source files? Having them in the header makes the header a complete description of the API, but then 90% of the lines in the header can easily be comments. Having them in the source has them close to the actual implementation, and is more consistent for static functions that can only be documented in the source.
    • Comments that describe how things are implemented but do not influence the API should probably go into the source file, and perhaps marked with \internal so that they can be excluded from the documentation.
    • We probably want at least two different levels of documentation generated from the source: public API documentation and full documentation for Gromacs developers. If these two suffice, it is probably easiest to use \internal for comments that are not part of the public API. One should probably write guidelines for where to put the \internal command; for example, setting the documentation for a file to be completely internal actually excludes also all functions in that file without explicitly specifying the command for each of them, and we might or might not want to use that.
    • What style of Doxygen comments to use? Most of the existing comments now use Qt style comments (/*! */, \command), but the selection code uses JavaDoc comments (/** */, @command) for brief comments with JAVADOC_AUTOBRIEF turned on, because //! doesn't work in C89. Mixed comments work without problems, but consistency would be a good thing.
    • How to organize the documentation? Doxygen allows for documentation pages that are not directly associated with any files, so these should have some common structure across the whole source. Labels on these pages are also global, which means that they should be carefully named. Currently, the main page is generated from include/mainpage.h. Doxygen also makes it possible to define groups that can contain functions, classes, files etc., in practice anything that you can document with Doxygen, and these groups can also contain documentation. Functions, typedefs etc. can belong to only one group, but classes, files, and other compound objects can belong to multiple groups. This makes groups particularly useful for C++ code, where there are only few functions outside classes. We could have, e.g., a group for each module, and a separate group for all public API functions.

    Proposal for Doxygen usage

    Here's a proposal of how things could be done (for C++, some of the grouping stuff doesn't work that well for C code). Feel free to comment and/or add things.

    General things:

    • Use the Qt-style comments, like this:
    /*! \brief
     * Performs a simple operation.
     *
     * \param[in] value  Input value.
     * \retval 0 on success.
     *
     * Detailed description.
     */
    int function(int value);
    
    • If there is only a brief description, it can be specified with "//! Brief description."
    • After adding a significant amount of comments, run it through doxygen with all the different settings (setting files generated by cmake at the root of the build tree) to see that the result is what you want. Pay attention to warnings that Doxygen generates when you run it, but notice that in order to hide some things from the public API documentation, it may be necessary to accept some warnings when using these settings (Doxyfile-user in particular).

    What to document, where, and how to mark different classes of documentation:

    • Document the usage of all elements in the header file where they are defined if there is one. Implementation-specific comments that don't influence how the function is used should go into the the source file, with an \internal tag in the beginning of the comment block.
    • For every entity that is part of the public API, add a \inpublicapi command at the end of the documentation block. For entities that are designed to be used outside their module within the library, but that users would not normally use, put a \inlibraryapi command at the end and \libinternal in the beginning. For intra-module entities, put \internal in the beginning. These commands are redefined in the different configuration files to generate a group containing the public API, and to control whether to generate documentation for the intra-library API. There are also conditional sections called libapi and internal for use with \if and \cond.
    • If there is a lot of entities in the same file that should all be added, you can use (should go inside all namespace declarations to work properly):
    /*! \addtopublicapi
     * \{
     */
    
    <declarations>
    
    /*!\}*/
    • There is a similar construct \addtolibraryapi, but that should be used with care, as it can easily add unintended functions to be visible in the public API docs. TODO: figure out how it should be used to not to cause that.
    • Classes appear always in Doxygen documentation, even if their enclosing file is not documented. So start the documentation blocks of classes that are not part of the public API with \internal or \libinternal.
    • In each file, add a comment block that describes the contents of the file right after the copyright notice. Mark the block with the \internal or \libinternal tag if it is not part of the public API (mark all source files with \internal as well). Format the comment block like this:
    /*! [\[lib]internal] \file
     * \brief
     * Brief description of the file.
     *
     * More details on the file if needed.
     *
     * \author Author Name <author.name@email.com>
     * [\in(public|library)api]
     * \ingroup module_MODULENAME
     */
    • When you make significant modifications to a file, you should add an \author line for yourself.

    Documenting modules:

    • For each module, decide on a header file that is the most important one for that module. In that header, add a documentation block like this (replace NAME with the directory name of the module, and group_utilitymodules with the proper group for the module):
    /*! \defgroup module_NAME Title of the module
     * \ingroup group_utilitymodules
     * \brief
     * Brief description of the module.
     *
     * Detailed description of the purpose and API of the module.
     * Should link to the header files and the most important functions/classes
     * in the module.
     *
     * \author Author Name <author.name@email.com>
     */
    • In that same header, document the namespace for that module.
    • For all compound entities (in doxygen terminology: classes, files, namespaces) that belong to the module, add a \ingroup module_NAME to the end of the documentation block. This can't be done for functions, typedefs or enums that are part of the public API, because these can only belong to one group. A point for discussion: perhaps this should only be done for entities that are not internal to the module?
    Page last modified 16:50, 24 Aug 2011 by tmurtola