Documentation Style
- Rule: Write correct English
Nowadays most editors provide interactive spell checking, including for sources (strings and comments). For instance, see
flyspell-mode
in Emacs, and in particular theflyspell-prog-mode
. To trigger this automatically, install the following in your~/.emacs.el
:(add-hook 'c-mode-hook 'flyspell-prog-mode 1) (add-hook 'c++-mode-hook 'flyspell-prog-mode 1) (add-hook 'cperl-mode-hook 'flyspell-prog-mode 1) (add-hook 'makefile-mode-hook 'flyspell-prog-mode 1) (add-hook 'python-mode-hook 'flyspell-prog-mode 1) (add-hook 'sh-mode-hook 'flyspell-prog-mode 1)
and so forth.
End comments with a period.
- Rule: Be concise
For documentation as for any other kind of writing, the shorter, the better: hunt useless words. See The Elements of Style, for an excellent set of writing guidelines.
Here are a few samples of things to avoid:
- Don’t document the definition instead of its object
Don’t write:
/// Declaration of the Foo class. class Foo { ... };
Of course you’re documenting the definition of the entities! “Declaration of the” is totally useless, just use
/// Foo class
. But read bellow.- Don’t qualify obvious entity kinds
Don’t write:
/// Foo class. class Foo { public: /// Construct a Foo object. Foo(Bar& bar) ... };
It is so obvious that you’re documenting the class and the constructor that you should not write it down. Instead of documenting the kind of an entity (class, function, namespace, destructor…), document its goal.
/// Wrapper around Bar objects. class Foo { public: /// Bind to \a bar. Foo(Bar& bar) ... };
- Rule: Use the Imperative
Use the imperative when documenting, as if you were giving order to the function or entity you are describing. When describing a function, there is no need to repeat “function” in the documentation; the same applies obviously to any syntactic category. For instance, instead of:
/// \brief Swap the reference with another. /// The method swaps the two references and returns the first. ref& swap(ref& other);
write:
/// \brief Swap the reference with another. /// Swap the two references and return the first. ref& swap(ref& other);
The same rules apply to ChangeLogs.
- Rule: Write Documentation in Doxygen
Documentation is a genuine part of programming, just as testing. We use Doxygen (Doxygen) to maintain the developer documentation of the Tiger Compiler. The quality of this documentation can change the grade.
Beware that Doxygen puts the first letter of documentation in upper case. As a result,
/// \file ast/arrayexp.hh /// \brief ast::ArrayExp declaration.
will not work properly, since Doxygen will transform
ast::ArrayExp
intoAst::ArrayExp
, which will not be recognized as an entity name. As a workaround, write the slightly longer:/// \file ast/arrayexp.hh /// \brief Declaration of ast::ArrayExp.
Of course, Doxygen documentation is not appropriate everywhere.
- Rule: Use
directive
Prefer backslash (\) to the commercial at (@) to specify directives.
- Rule: Prefer C Comments for Long Comments
Prefer C comments (
/** ... */
) to C++ comments (/// ...
). This is to ensure consistency with the style we use.- Rule: Prefer C++ Comments for One Line Comments
Because it is lighter, instead of
/** \brief Name of this program. */ extern const char* program_name;
prefer
/// Name of this program. extern const char* program_name;
For instance, instead of
/* Construct an InterferenceGraph. */ InterferenceGraph(const std::string& name, const assem::instrs_t& instrs, bool trace = false);
or
/** @brief Construct an InterferenceGraph. ** @param name its name, hopefully based on the function name ** @param instrs the code snippet to study ** @param trace trace flag **/ InterferenceGraph(const std::string& name, const assem::instrs_t& instrs, bool trace = false);
or
/// \brief Construct an InterferenceGraph. /// \param name its name, hopefully based on the function name /// \param instrs the code snippet to study /// \param trace trace flag InterferenceGraph(const std::string& name, const assem::instrs_t& instrs, bool trace = false);
write
/** \brief Construct an InterferenceGraph. \param name its name, hopefully based on the function name \param instrs the code snippet to study \param trace trace flag */ InterferenceGraph(const std::string& name, const assem::instrs_t& instrs, bool trace = false);