/** @page libsbml-coding Coding conventions for libSBML The following is a collection of guidelines for libSBML authors and other interested persons to follow when writing libSBML code and documenting it.
@ref coding-general @n @ref coding-doxygen-summary @n @ref coding-doc-h @n @ref coding-doc-cpp @n
LibSBML's application programming interface (API) is documented using a combination of tools: for C++, C and Python, we use the open-source software tool Doxygen, written by Dimitri van Heesch, and for the Java API, we use Javadoc. In addition to these main tools, we use several scripts to massage the output of SWIG to produce better documentation. The guidelines presented in this section are oriented towards explaining how to organize code comments such that Doxygen can produce good output, yet simultaneously make the comments in the code be readable on their own. @section coding-general General guidelines @li Doxygen (and some humans) look in the .h file for a C++ class definition. Doxygen is a bit annoying in this regard because the content of the .h file overrides the content of the .cpp file for the class members (the methods and the data members). That is, if you only modify the comments in the class definition in the .cpp file, the changes will not be reflected in the documentation produced by Doxygen. Thus, when documenting a class, concentrate on the .h files. However, and confusingly, C functions must be documented in the .cpp files. Thus, the rule is: document classes in .h files, but document C functions in the .cpp files. @li Doxygen tags can be prefixed with either @c \@ or @c \\. Since it doesn't matter which, we may as well use the @c \@ form because it's also used by Javadoc (and thus is easier to remember for Java programmers). @li Doxygen comments consist of a C-style comment block beginning with two asterisks (@c *) characters, as in the following example: @verbatim /** * Comments within which commands for Doxygen begin with the character @. */ @endverbatim If your comment does @em not begin with /**, then it will be ignored by Doxygen. This can be either bad or good, depending on the intention behind the comment. @li Please write in complete sentences, with correct English grammar and punctuation. @em Do @em not treat new lines as new sentences or beginnings of different comments. Here is an example of what should be @em avoided: @verbatim /** * creates a foo object * given arg is the template */ @endverbatim The text above doesn't end sentences with periods, doesn't begin sentences with capitals, doesn't form complete sentences, etc. When Doxygen is used to generate HTML documentation from this, it turns into one long run-on paragraph, and it's unreadable. @li Please write sentences with @em two (2) spaces after the terminating period, not one. First, this makes the resulting text easier to read compared to when sentence-ending periods are followed by only one space. Second, text editing programs such as Emacs have special features to recognize sentences based on this pattern, and they make proficient users of those editors much happier because they can use sentence-oriented editing commands. @li Watch out that Doxygen automatically turns entity names it recognizes in text into links to the definition of that entity. This is usually what you want to have happen; for example, when describing the Model class, you may mention classes such as Species and Compartment, and those should be turned into convenient links to their definitions in the API documentation. However, sometimes you don't want that to happen. To prevent Doxygen from linking a word, put a percentage sign (\%) in front of it, as in @c \%%Model. Doxygen will remove the percentage sign and leave the rest of the word unlinked, resulting in the plain word %Model appearing in the finished document. @li We are using a feature of Doxygen that makes it use the first sentence of a documentation comment as the "brief" description of the entity being described (which may be a class, a method, a class data member, a function, a typedef, etc.). This means that the first sentence up to a period or a blank line will be pulled out separately and used as a one-line summary in certain contexts by Doxygen. The following is an example: @verbatim /** * This is the brief description. After the first sentence, everything * else is part of the detailed description and not the brief one. This * third sentence is also part of the detailed description. */ @endverbatim Consequently, to emphasize this and remind people that this is going to happen when the API documentation is generated, it is better to format the text in the as in the following example: @verbatim /** * This is the brief description. * * This is the beginning of the detailed description.... */ @endverbatim The visual split makes it really obvious what's going to happen. @li Please try to limit lengths of lines to 79 characters long or less. This makes code and documentation generally easier to read and edit in different software tools. Sometimes it's too difficult to avoid a long line, and then it's okay, but generally it's possible to reformat code in such away as to keep things to 79 characters. @li Sometimes code is meant to be part of the internal implementation and not advertised to users of the library. To make Doxygen ignore blocks of code, wrap the code with the comment @verbatim /** @cond doxygen-libsbml-internal */ @endverbatim at the beginning and @verbatim /** @endcond doxygen-libsbml-internal */ @endverbatim at the end of the block. (Explanation: this sets up a conditional that will only be "seen" by Doxygen if the symbol "doxygen-libsbml-internal" is defined. Since it's never defined in the Doxygen configuration, it will the block will be ignored.) @section coding-doxygen-summary Summary of commonly-used Doxygen commands in libSBML The following is a summary of the doxygen commands we have found useful so far in documenting libSBML. This is only intended as a quick orientation; they are illustrated in the other sections below, and the complete details of their definitions and use can be found online at the Doxygen website.
Command Meaning
\@file Defines the name of the current file.
\@brief Provides a one-sentence description of the entity being described (a file, a class, etc.).
\@author Names the author of the entity being described (a file, a class, etc.).
\@c Puts the following word in typewriter ("code") font. To style more than one word, use <code>the words</code>. If you need to put something that contains HTML tags in typewriter font, use the <code>the words</code> form, and use the HTML character codes \< and\> to embed the openening '@c <' and '@c >' characters inside the words.
\@em Puts the following word in italic font, for emphasis. To put multiple words in italics, use <em>the words</em>.
\@n Forces a newline, like HTML's <br>.
\@p Puts the following word in typewriter ("code") font. This form is preferred when the word is a parameter to a method or function.
\@li Starts (or continues) a bullet list. You can insert the first @c \@li in a comment, and the item will continue until a paragraph break or the next @c \@li command. (Note: even though Doxygen will also recognize hyphens at the beginning of a line as starting a list item, avoid using that approach in favor of the @c \@li command.
\@class Declares that the following documentation block refers to the named class. Useful only when the block does not immediately precede the class definition (e.g., when it's at the beginning of the file).
\@param Declares a parameter to a method or function. The first word following @c \@param will be the name of the parameter, and the rest of the text (up to a period or blank) will be used as the description.
\@return Declares the return value from a method or function.
\@see Formats a reference to another entity in the documentation. Commonly used to refer to related classes or methods.
\@note Formats the following paragraph with the heading "Note:". Useful to call out something special about a class, function, file or other entity, such as a behavior that should be brought to the attention of users or a note about API changes compared to previous versions of the software or SBML. As a convention, please put @c \@note blocks at the end of a documentation block, for uniformity in the API documentation.
\@warning Formats the following paragraph with the heading "Warning:". This is a stronger statement than \@note, and is useful to call attention to backward-incompatible changes or potentially error-provoking situations. As a convention, please put @c \@warning blocks at the end of a documentation block, for uniformity in the API documentation.
\@bug Formats the following paragraph with the heading "Bugs:". Useful to indicate that something is known to be a problem in some part of the code. As a convention, please put @c \@bug blocks at the end of a documentation block, for uniformity in the API documentation.
Many HTML commands will work in comments for Doxygen. For example, a common one is the @c a tag for linking text to a URL, as in <a href="http://sbml.org">home page</a>. @section coding-doc-h Guidelines for documenting .h files It is important to note that the documentation of global functions, variables, typedefs, and enums will only be included in the output of Doxygen if the file they are in is documented as well. @li Here is a template header file suitable for use when creating a new .h file for libSBML (and in fact, it's the same for .cpp files, too): @verbatim /** * @file [filename] * @brief [succinct description of what's in this file] * @author [author's name] * * $Id$ * $HeadURL$ * **/ @endverbatim Of course, you should substitute appropriate content where the text is bracked by @c [ and @c ]. The @c $Id$ and @c $HeadURL$ keywords will automatically be substituted by CVS or SVN upon the first check-in. The following is an complete example taken from an actual libSBML file at the time of this writing: @verbatim /** * @file Compartment.h * @brief The libSBML class of object implementing SBML's Compartment. * @author Ben Bornstein * * $Id: libsbml-coding.txt 7249 2008-06-26 22:48:40Z bbornstei $ * $HeadURL: https://sbml.svn.sourceforge.net/svnroot/sbml/trunk/libsbml/src/sbml/Compartment.h $ * **/ #ifndef Compartment_h #define Compartment_h ... @endverbatim @li A .h file will typically have a class declaration in it. The @em normal way that one would document the class is to put a comment block in front of the class declaration, as in the following fragment: @verbatim /** * The libSBML class implementing SBML's CompartmentType construct. * * CompartmentTypes in SBML are ... */ class LIBSBML_EXTERN CompartmentType : public SBase { public: ... @endverbatim Unfortunately, we are hit here by a small problem of how to generate descriptions for different programming languages from the same source files. In particular, those class declarations in the .h files are usually surrounded by \#ifdef __cplusplus, which means they become invisible when we use Doxygen to generate the descriptions for anything other than C++. Thus, for the special case of documentation of classes, please put the documentation in the file header rather that ahead of the class itself in the file. The following example illustrates this procedure (and note how more than one class can be described in the header): @verbatim /** * @file CompartmentType.h * @brief Definitions of CompartmentType and ListOfCompartmentTypes. * @author Ben Bornstein * * $Id: CompartmentType.h 7249 2008-06-26 22:48:40Z mhucka $ * $Source: /cvsroot/sbml/libsbml/src/sbml/CompartmentType.h,v $ * * * * @class CompartmentType. * @brief LibSBML implementation of SBML's %CompartmentType construct. * * A compartment type in SBML is a grouping construct used to * establish a relationship between multiple Compartment objects. * .... * * * @class ListOfCompartmentTypes. * @brief LibSBML implementation of SBML's ListOfCompartmentTypes construct. * * The various ListOf___ classes in SBML are merely containers used for * organizing the main components of an SBML model. All are derived from *.... */ #ifndef CompartmentType_h #define CompartmentType_h ... @endverbatim @li For each method or data member in the class definition, include a comment block ahead of it, making sure to provide at least a brief description. If it's a method and the method returns a value, use @c \@return to describe the returned value; if it takes parameters, use @c \@param to describe the parameters. If you also need to refer to the parameters in the textual description of the method, use the @c \@p command. The following example illustrates this: @verbatim /** * Creates a new CompartmentType, optionally with the given @p id and * @p name attribute values. * * In SBML, identifiers are required for CompartmentType objects; * however, the identifier does not have to be set at the time of * creation of the object, and instead can be set using the setId() * method on the SBase parent class. * * @param id a string, the identifier of this CompartmentType instance * @param name a string, the optional name of this */ CompartmentType (const std::string& id = "", const std::string& name = ""); @endverbatim @li Please try to leave 2 blank lines between method declarations and other items in the definitions of classes. This makes it easier for the eye to spot transitions between method definitions, despite the blank lines that exist within comment blocks. Here is an example taken from a class definition in a .h file: @verbatim class LIBSBML_EXTERN CompartmentType : public SBase { public: /** * Creates a new CompartmentType, optionally with the given @p id and @p * name attribute values. * * In SBML, identifiers are required for CompartmentType objects; * however, the identifier does not have to be set at the time of * creation of the object, and instead can be set using the setId() * method on the SBase parent class. * * @param id a string, the identifier of this CompartmentType instance * @param name a string, the optional name of this */ CompartmentType (const std::string& id = "", const std::string& name = ""); /** * Destroys this CompartmentType. */ virtual ~CompartmentType (); /** * Copy constructor; creates a copy of this CompartmentType. */ CompartmentType(const CompartmentType& orig); /** * Assignment operator for CompartmentType. */ CompartmentType& operator=(const CompartmentType& orig); @endverbatim @section coding-doc-cpp Guidelines for documenting .cpp files The .cpp files can be handled very similarly to the .h files described above. You may use the same header template shown in the previous section about .h files, and all the same guidelines apply. The principal difference is that it is not necessary to repeat the class description placed in the .h file, nor indeed is it necessary to copy or recreate the documentation of class methods. As already mentioned, when the API manual is generated by Doxygen, it will use the comments from the .h file as the source of the documentation for the class and methods. However, it @em is important to document @em functions, because these are not defined by the .h files. This is especially important for the C wrappers around the C++ methods. All the same documentation conventions described so far apply to describing functions. The following example provides an illustration: @verbatim /** * Creates a new CompartmentType with the given @p id and @p name attribute * values. * * In SBML Level 2 and beyond, the identifier attribute of a * CompartmentType is required to have a value, but the name is optional. * Programs calling this function can legitimately use an empty string for * the @p name parameter. * * @param sid the value to assign as the identifier of this CompartmentType * @param name the value to assign as the name of this CompartmentType * * @return a pointer to the newly created CompartmentType_t structure. */ LIBSBML_EXTERN CompartmentType_t * CompartmentType_createWith (const char *sid, const char *name); @endverbatim @section coding-misc-doxygen Miscellaneous Doxygen notes @li The doxygen command @c \@internal is (according to the doxygen documentation) supposed to let you flag things as internal implementation code, such that it is not put in the finished documentation. This would be great if we could use it, but I (MH) have been unable to make this work. (Yes, there is a configuration flag, and yes, I've tried setting it both ways.) */