ENH: No verbose a2x output when building UserGuide
[freefoam.git] / doc / codingStyleGuide.org
blob589f946839ae71c55add34c9cd7b7e312ccc5a72
1 #                            -*- mode: org; -*-
3 #+TITLE:                 OpenFOAM C++ style guide
4 #+AUTHOR:                      OpenCFD Ltd.
5 #+DATE:                         June 2010
6 #+LINK:                  http://www.opencfd.co.uk
7 #+OPTIONS: author:nil ^:{}
9 * OpenFOAM C++ style guide
11 *** General
12     + 80 character lines max
13     + The normal indentation is 4 spaces per logical level.
14     + Use spaces for indentation, not tab characters.
15     + Avoid trailing whitespace.
16     + The body of control statements (eg, =if=, =else=, =while=, etc). is
17       always delineated with brace brackets. A possible exception can be
18       made in conjunction with =break= or =continue= as part of a control
19       structure.
20     + The body of =case= statements is usually delineated with brace brackets.
21     + A fall-through =case= should be commented as such.
23     + stream output
24       + =<<= is always four characters after the start of the stream,
25         so that the =<<= symbols align, i.e.
27 #+BEGIN_EXAMPLE
28     Info<< ...
29     os  << ...
30 #+END_EXAMPLE
32       so
34 #+BEGIN_EXAMPLE
35     WarningIn("className::functionName()")
36         << "Warning message"
37 #+END_EXAMPLE
39       NOT
41 #+BEGIN_EXAMPLE
42     WarningIn("className::functionName()")
43     << "Warning message"
44 #+END_EXAMPLE
47     + no unnecessary class section headers, i.e. remove
49 #+BEGIN_EXAMPLE
50     // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
52     // Check
54     // Edit
56     // Write
57 #+END_EXAMPLE
60       if they contain nothing, even if planned for 'future use'
62     + class titles are centred
64 #+BEGIN_EXAMPLE
65     /*---------------------------------------------------------------------------*\
66                             Class exampleClass Declaration
67     \*---------------------------------------------------------------------------*/
68 #+END_EXAMPLE
70       NOT
72 #+BEGIN_EXAMPLE
73     /*---------------------------------------------------------------------------*\
74                 Class exampleClass Declaration
75     \*---------------------------------------------------------------------------*/
76 #+END_EXAMPLE
78 *** The /.H/ Files
79     + header file spacing
80       + Leave two empty lines between sections
81         (as per functions in the /.C/ file etc)
83     + use =//- Comment= comments in header file
84       + add descriptions to class data and functions
85     + destructor
86       + If adding a comment to the destructor -
87         use =//-= and code as a normal function:
89 #+BEGIN_EXAMPLE
90     //- Destructor
91     ~className();
92 #+END_EXAMPLE
94     + inline functions
95       + Use inline functions where appropriate in a separate /classNameI.H/ file.
96         Avoid cluttering the header file with function bodies.
98 *** The /.C/ Files
99     + Do not open/close namespaces in a /.C/ file
100       + Fully scope the function name, i.e.
102 #+BEGIN_EXAMPLE
103     Foam::returnType Foam::className::functionName()
104 #+END_EXAMPLE
106       NOT
108 #+BEGIN_EXAMPLE
109     namespace Foam
110     {
111         ...
112         returnType className::functionName()
113         ...
114     }
115 #+END_EXAMPLE
117       EXCEPTION
119       When there are multiple levels of namespace, they may be used in the /.C/
120       file, i.e.
122 #+BEGIN_EXAMPLE
123     namespace Foam
124     {
125     namespace compressible
126     {
127     namespace RASModels
128     {
129         ...
130     } // End namespace RASModels
131     } // End namespace compressible
132     } // End namespace Foam
133 #+END_EXAMPLE
135     + Use two empty lines between functions
137 *** Coding Practice
138     + passing data as arguments or return values.
139       + Pass bool, label and scalar as copy, anything larger by reference.
141     + const
142       + Use everywhere it is applicable.
144     + variable initialisation using
145 #+BEGIN_EXAMPLE
146     const className& variableName = otherClass.data();
147 #+END_EXAMPLE
149       NOT
151 #+BEGIN_EXAMPLE
152     const className& variableName(otherClass.data());
153 #+END_EXAMPLE
155     + virtual functions
156       + If a class is virtual, make all derived classes virtual.
158 *** Conditional Statements
159 #+BEGIN_EXAMPLE
160     if (condition)
161     {
162         code;
163     }
164 #+END_EXAMPLE
166     OR
168 #+BEGIN_EXAMPLE
169     if
170     (
171        long condition
172     )
173     {
174         code;
175     }
176 #+END_EXAMPLE
178     NOT (no space between =if= and =(= used)
180 #+BEGIN_EXAMPLE
181     if(condition)
182     {
183         code;
184     }
185 #+END_EXAMPLE
187 *** =for= and =while= Loops
189 #+BEGIN_EXAMPLE
190     for (i = 0; i < maxI; i++)
191     {
192         code;
193     }
194 #+END_EXAMPLE
196     OR
198 #+BEGIN_EXAMPLE
199     for
200     (
201         i = 0;
202         i < maxI;
203         i++
204     )
205     {
206         code;
207     }
208 #+END_EXAMPLE
210     NOT this (no space between =for= and =(= used)
212 #+BEGIN_EXAMPLE
213     for(i = 0; i < maxI; i++)
214     {
215         code;
216     }
217 #+END_EXAMPLE
219     Note that when indexing through iterators, it is often slightly more
220     efficient to use the pre-increment form. Eg, =++iter= instead of =iter++=
222 *** =forAll=, =forAllIter=, =forAllConstIter=, etc. loops
223     like =for= loops, but
225 #+BEGIN_EXAMPLE
226     forAll(
227 #+END_EXAMPLE
229     NOT
231 #+BEGIN_EXAMPLE
232     forAll (
233 #+END_EXAMPLE
235     Using the =forAllIter= and =forAllConstIter= macros is generally
236     advantageous - less typing, easier to find later.  However, since
237     they are macros, they will fail if the iterated object contains
238     any commas.
240     The following will FAIL!:
242 #+BEGIN_EXAMPLE
243     forAllIter(HashTable<labelPair, edge, Hash<edge> >, foo, iter)
244 #+END_EXAMPLE
246     These convenience macros are also generally avoided in other
247     container classes and OpenFOAM primitive classes.
249 *** Splitting Over Multiple Lines
251 **** Splitting return type and function name
252      + split initially after the function return type and left align
254      + do not put =const= onto its own line - use a split to keep it with
255        the function name and arguments.
257      so
259 #+BEGIN_EXAMPLE
260      const Foam::longReturnTypeName&
261      Foam::longClassName::longFunctionName const
262 #+END_EXAMPLE
264      NOT
266 #+BEGIN_EXAMPLE
267      const Foam::longReturnTypeName&
268          Foam::longClassName::longFunctionName const
269 #+END_EXAMPLE
271      NOR
273 #+BEGIN_EXAMPLE
274      const Foam::longReturnTypeName& Foam::longClassName::longFunctionName
275      const
276 #+END_EXAMPLE
278      NOR
280 #+BEGIN_EXAMPLE
281      const Foam::longReturnTypeName& Foam::longClassName::
282      longFunctionName const
283 #+END_EXAMPLE
285      + if it needs to be split again, split at the function name (leaving
286        behind the preceding scoping =::=s), and again, left align, i.e.
288      For example,
290 #+BEGIN_EXAMPLE
291      const Foam::longReturnTypeName&
292      Foam::veryveryveryverylongClassName::
293      veryveryveryverylongFunctionName const
294 #+END_EXAMPLE
296 **** Splitting long lines at an "="
298      Indent after split
300 #+BEGIN_EXAMPLE
301      variableName =
302          longClassName.longFunctionName(longArgument);
303 #+END_EXAMPLE
305      OR (where necessary)
307 #+BEGIN_EXAMPLE
308      variableName =
309          longClassName.longFunctionName
310          (
311              longArgument1,
312              longArgument2
313          );
314 #+END_EXAMPLE
316      NOT
318 #+BEGIN_EXAMPLE
319      variableName =
320      longClassName.longFunctionName(longArgument);
321 #+END_EXAMPLE
323      NOR
325 #+BEGIN_EXAMPLE
326      variableName = longClassName.longFunctionName
327      (
328          longArgument1,
329          longArgument2
330      );
331 #+END_EXAMPLE
333 *** Maths and Logic
334     + operator spacing
336 #+BEGIN_EXAMPLE
337       a + b, a - b
338       a*b, a/b
339       a & b, a ^ b
340       a = b, a != b
341       a < b, a > b, a >= b, a <= b
342       a || b, a && b
343 #+END_EXAMPLE
345     + splitting formulae over several lines
347       Split and indent as per "splitting long lines at an ="
348       with the operator on the lower line.  Align operator so that first
349       variable, function or bracket on the next line is 4 spaces indented i.e.
351 #+BEGIN_EXAMPLE
352     variableName =
353         a * (a + b)
354       - exp(c/d)
355       * (k + t);
356 #+END_EXAMPLE
358       This is sometimes more legible when surrounded by extra parentheses:
360 #+BEGIN_EXAMPLE
361     variableName =
362     (
363         a * (a + b)
364       - exp(c/d)
365       * (k + t)
366     );
367 #+END_EXAMPLE
369     + splitting logical tests over several lines
371       outdent the operator so that the next variable to test is aligned with
372       the four space indentation, i.e.
374 #+BEGIN_EXAMPLE
375     if
376     (
377         a == true
378      && b == c
379     )
380 #+END_EXAMPLE
382 ** Documentation
384 *** General
386     + For readability in the comment blocks, certain tags are used that are
387       translated by pre-filtering the file before sending it to Doxygen.
389     + The tags start in column 1, the contents follow on the next lines and
390       indented by 4 spaces. The filter removes the leading 4 spaces from the
391       following lines until the next tag that starts in column 1.
393     + The 'Class' and 'Description' tags are the most important ones.
395     + The first paragraph following the 'Description' will be used for the
396       brief description, the remaining paragraphs become the detailed
397       description.
399       For example,
401 #+BEGIN_EXAMPLE
402     Class
403         Foam::myClass
405     Description
406         A class for specifying the documentation style.
408         The class is implemented as a set of recommendations that may
409         sometimes be useful.
410 #+END_EXAMPLE
412     + The class name must be qualified by its namespace, otherwise Doxygen
413       will think you are documenting some other class.
415     + If you don't have anything to say about the class (at the moment), use
416       the namespace-qualified class name for the description. This aids with
417       finding these under-documented classes later.
420 #+BEGIN_EXAMPLE
421     Class
422         Foam::myUnderDocumentedClass
424     Description
425         Foam::myUnderDocumentedClass
426 #+END_EXAMPLE
429     + Use 'Class' and 'Namespace' tags in the header files.
430       The Description block then applies to documenting the class.
432     + Use 'InClass' and 'InNamespace' in the source files.
433       The Description block then applies to documenting the file itself.
436 #+BEGIN_EXAMPLE
437     InClass
438         Foam::myClass
440     Description
441         Implements the read and writing of files.
442 #+END_EXAMPLE
444 *** Doxygen Special Commands
446     Doxygen has a large number of special commands with a =\= prefix or
447     (alternatively) an =@= prefix.
449     The =@= prefix form is recommended for most Doxygen specials, since it
450     has the advantage of standing out. It also happens to be what projects
451     like gcc and VTK are using.
453     The =\= prefix form, however, looks a bit better for the =\n= newline
454     command and when escaping single characters - eg, =\@=, =\<=, =\>=, etc.
456     Since the filtering removes the leading 4 spaces within the blocks, the
457     Doxygen commmands can be inserted within the block without problems.
460 #+BEGIN_EXAMPLE
461     InClass
462         Foam::myClass
464     Description
465         Implements the read and writing of files.
467         An example input file:
468         @verbatim
469             patchName
470             {
471                 type        myPatchType;
472                 refValue    100;
473                 value       uniform 1;
474             }
475         @endverbatim
477         Within the implementation, a loop over all patches is done:
478         @code
479             forAll(patches, patchI)
480             {
481                 ...  // some operation
482             }
483         @endcode
484 #+END_EXAMPLE
486 *** HTML Special Commands
488     Since Doxygen also handles HTML tags to a certain extent, the angle
489     brackets need quoting in the documentation blocks. Non-HTML tags cause
490     Doxygen to complain, but seem to work anyhow.
492     eg,
493     + The template with type =<HR>= is a bad example.
495     + The template with type =\<HR\>= is a better example.
497     + The template with type =<Type>= causes Doxygen to complain about an
498       unknown html type, but it seems to work okay anyhow.
501 *** Documenting Namespaces
503     + If namespaces are explictly declared with the =Namespace()= macro,
504       they should be documented there.
506     + If the namespaces is used to hold sub-models, the namespace can be
507       documented in the same file as the class with the model selector.
508       eg,
510 #+BEGIN_EXAMPLE
511     documented namespace 'Foam::functionEntries' within the
512     class 'Foam::functionEntry'
513 #+END_EXAMPLE
515     + If nothing else helps, find some sensible header.
516       eg,
518 #+BEGIN_EXAMPLE
519     namespace 'Foam' is documented in the foamVersion.H file
520 #+END_EXAMPLE
523 *** Documenting typedefs and classes defined via macros
525     ... not yet properly resolved
528 *** Documenting Applications
530     Any number of classes might be defined by a particular application, but
531     these classes will not, however, be available to other parts of
532     OpenFOAM. At the moment, the sole purpuse for running Doxygen on the
533     applications is to extract program usage information for the '-doc'
534     option.
536     The documentation for a particular application is normally contained
537     within the first comment block in a /.C/ source file. The solution is this
538     to invoke a special filter for the "/applications/{solver,utilities}/"
539     directories that only allows the initial comment block for the /.C/ files
540     through.
542     The layout of the application documentation has not yet been finalized,
543     but foamToVTK shows an initial attempt.
545 *** Orthography (an opinion)
547     Given the origins of OpenFOAM, the British spellings (eg, neighbour and
548     not neighbor) are generally favoured. For code sections that interact
549     with external libraries, it can be useful to adopt American spellings,
550     especially for names that constitute a significant part of the external
551     library - eg, 'color' within graphics sub-systems.
553     Both '-ize' and the '-ise' variant are found in the code comments. If
554     used as a variable or class method name, it is probably better to use
555     '-ize', which is considered the main form by the Oxford University
556     Press.
558     Eg,
559 #+BEGIN_EXAMPLE
560     myClass.initialize()
561 #+END_EXAMPLE
563     The word "its" (possesive) vs. "it's" (colloquial for "it is" or "it has")
564     seems to confuse non-native (and some native) English speakers.
565     It is better to donate the extra keystrokes and write "it is" or "it has".
566     Any remaining "it's" are likely an incorrect spelling of "its".