Merge branch 'master' of github.com:OpenFOAM/OpenFOAM-2.0.x
[OpenFOAM-2.0.x.git] / doc / codingStyleGuide.org
bloba6e8208e0ad8f7e8a59a2af5c81fc035b9eb6be4
1 #                            -*- mode: org; -*-
3 #+TITLE:               OpenFOAM C++ style guide
4 #+AUTHOR:                      OpenFOAM Foundation
5 #+DATE:                             Aug 2011
6 #+LINK:                     http://www.OpenFOAM.org
7 #+OPTIONS: author:nil ^:{}
8 #+STARTUP: hidestars
9 #+STARTUP: odd
11 * OpenFOAM C++ style guide
12 *** General
13     + 80 character lines max
14     + The normal indentation is 4 spaces per logical level.
15     + Use spaces for indentation, not tab characters.
16     + Avoid trailing whitespace.
17     + The body of control statements (eg, =if=, =else=, =while=, etc). is
18       always delineated with brace brackets. A possible exception can be
19       made in conjunction with =break= or =continue= as part of a control
20       structure.
21     + The body of =case= statements is usually delineated with brace brackets.
22     + A fall-through =case= should be commented as such.
24     + stream output
25       + =<<= is always four characters after the start of the stream,
26         so that the =<<= symbols align, i.e.
27         #+BEGIN_SRC c++
28         Info<< ...
29         os  << ...
30         #+END_SRC
31         so
32         #+BEGIN_SRC C++
33         WarningIn("className::functionName()")
34             << "Warning message"
35         #+END_SRC
36         *not*
37         #+BEGIN_SRC C++
38         WarningIn("className::functionName()")
39         << "Warning message"
40         #+END_SRC
42     + no unnecessary class section headers, i.e. remove
43 #+BEGIN_SRC C++
44 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
46     // Check
48     // Edit
50     // Write
51 #+END_SRC
52       if they contain nothing, even if planned for 'future use'
54     + class titles are centred
55 #+BEGIN_SRC C++
56 /*---------------------------------------------------------------------------*\
57                         Class exampleClass Declaration
58 \*---------------------------------------------------------------------------*/
59 #+END_SRC
61       *not*
63 #+BEGIN_SRC C++
64 /*---------------------------------------------------------------------------*\
65                 Class exampleClass Declaration
66 \*---------------------------------------------------------------------------*/
67 #+END_SRC
69 *** The /.H/ Files
70     + header file spacing
71       + Leave two empty lines between sections
72         (as per functions in the /.C/ file etc)
73     + use =//- Comment= comments in header file to add descriptions to class
74       data and functions do be included in the Doxygen documentation:
75       + text on the line starting with =//-= becomes the Doxygen brief
76         description;
77       + text on subsequent lines becomes the Doxygen detailed description /e.g./
78         #+BEGIN_SRC C++
79         //- A function which returns a thing
80         //  This is a detailed description of the function
81         //  which processes stuff and returns other stuff
82         //  depending on things.
83         thing function(stuff1, stuff2);
84         #+END_SRC
85       + list entries start with =-= or =-#= for numbered lists but cannot start
86         on the line immediately below the brief description so
87         #+BEGIN_SRC C++
88         //- Compare triFaces
89         //  Returns:
90         //  -  0: different
91         //  - +1: identical
92         //  - -1: same face, but different orientation
93         static inline int compare(const triFace&, const triFace&);
94         #+END_SRC
95         or
96         #+BEGIN_SRC C++
97         //- Compare triFaces returning 0, +1 or -1
98         //
99         //  -  0: different
100         //  - +1: identical
101         //  - -1: same face, but different orientation
102         static inline int compare(const triFace&, const triFace&);
103         #+END_SRC
104         *not*
105         #+BEGIN_SRC C++
106         //- Compare triFaces returning 0, +1 or -1
107         //  -  0: different
108         //  - +1: identical
109         //  - -1: same face, but different orientation
110         static inline int compare(const triFace&, const triFace&);
111         #+END_SRC
112       + list can be nested for example
113         #+BEGIN_SRC C++
114         //- Search for \em name
115         //  in the following hierarchy:
116         //  -# personal settings:
117         //    - ~/.OpenFOAM/\<VERSION\>/
118         //      <em>for version-specific files</em>
119         //    - ~/.OpenFOAM/
120         //      <em>for version-independent files</em>
121         //  -# site-wide settings:
122         //    - $WM_PROJECT_INST_DIR/site/\<VERSION\>
123         //      <em>for version-specific files</em>
124         //    - $WM_PROJECT_INST_DIR/site/
125         //      <em>for version-independent files</em>
126         //  -# shipped settings:
127         //    - $WM_PROJECT_DIR/etc/
128         //
129         //  \return the full path name or fileName() if the name cannot be found
130         //  Optionally abort if the file cannot be found
131         fileName findEtcFile(const fileName&, bool mandatory=false);
132         #+END_SRC
133       + for more details see the Doxygen documentation.
134     + destructor
135       + If adding a comment to the destructor -
136         use =//-= and code as a normal function:
137         #+BEGIN_SRC C++
138         //- Destructor
139         ~className();
140         #+END_SRC
141     + inline functions
142       + Use inline functions where appropriate in a separate /classNameI.H/
143         file.  Avoid cluttering the header file with function bodies.
145 *** The /.C/ Files
146     + Do not open/close namespaces in a /.C/ file
147       + Fully scope the function name, i.e.
148         #+BEGIN_SRC C++
149         Foam::returnType Foam::className::functionName()
150         #+END_SRC
151         *not*
152         #+BEGIN_SRC C++
153         namespace Foam
154         {
155             ...
156             returnType className::functionName()
157             ...
158         }
159         #+END_SRC
160         EXCEPTION
162         When there are multiple levels of namespace, they may be used in the
163         /.C/ file, i.e.
164         #+BEGIN_SRC C++
165         namespace Foam
166         {
167         namespace compressible
168         {
169         namespace RASModels
170         {
171             ...
172         } // End namespace RASModels
173         } // End namespace compressible
174         } // End namespace Foam
175         #+END_SRC
177     + Use two empty lines between functions
179 *** Coding Practice
180     + passing data as arguments or return values.
181       + Pass bool, label and scalar as copy, anything larger by reference.
182     + const
183       + Use everywhere it is applicable.
184     + variable initialisation using
185       #+BEGIN_SRC C++
186       const className& variableName = otherClass.data();
187       #+END_SRC
188       *not*
189       #+BEGIN_SRC C++
190       const className& variableName(otherClass.data());
191       #+END_SRC
192     + virtual functions
193       + If a class is virtual, make all derived classes virtual.
195 *** Conditional Statements
196     #+BEGIN_SRC C++
197     if (condition)
198     {
199         code;
200     }
201     #+END_SRC
202     OR
203     #+BEGIN_SRC C++
204     if
205     (
206        long condition
207     )
208     {
209         code;
210     }
211     #+END_SRC
212     *not* (no space between =if= and =(= used)
213     #+BEGIN_SRC C++
214     if(condition)
215     {
216         code;
217     }
218     #+END_SRC
220 *** =for= and =while= Loops
221     #+BEGIN_SRC C++
222     for (i = 0; i < maxI; i++)
223     {
224         code;
225     }
226     #+END_SRC
227     OR
228     #+BEGIN_SRC C++
229     for
230     (
231         i = 0;
232         i < maxI;
233         i++
234     )
235     {
236         code;
237     }
238     #+END_SRC
239     *not* this (no space between =for= and =(= used)
240     #+BEGIN_SRC C++
241     for(i = 0; i < maxI; i++)
242     {
243         code;
244     }
245     #+END_SRC
246     Note that when indexing through iterators, it is often slightly more
247     efficient to use the pre-increment form. Eg, =++iter= instead of =iter++=
249 *** =forAll=, =forAllIter=, =forAllConstIter=, etc. loops
250     like =for= loops, but
251     #+BEGIN_SRC C++
252     forAll(
253     #+END_SRC
254     *not*
255     #+BEGIN_SRC C++
256     forAll (
257     #+END_SRC
258     Using the =forAllIter= and =forAllConstIter= macros is generally
259     advantageous - less typing, easier to find later.  However, since
260     they are macros, they will fail if the iterated object contains
261     any commas.
263     The following will FAIL!:
265     #+BEGIN_SRC C++
266     forAllIter(HashTable<labelPair, edge, Hash<edge> >, foo, iter)
267     #+END_SRC
268     These convenience macros are also generally avoided in other
269     container classes and OpenFOAM primitive classes.
271 *** Splitting Over Multiple Lines
272 ***** Splitting return type and function name
273       + split initially after the function return type and left align
274       + do not put =const= onto its own line - use a split to keep it with
275         the function name and arguments.
276         #+BEGIN_SRC C++
277         const Foam::longReturnTypeName&
278         Foam::longClassName::longFunctionName const
279         #+END_SRC
280         *not*
281         #+BEGIN_SRC C++
282         const Foam::longReturnTypeName&
283             Foam::longClassName::longFunctionName const
284         #+END_SRC
285         *nor*
286         #+BEGIN_SRC C++
287         const Foam::longReturnTypeName& Foam::longClassName::longFunctionName
288         const
289         #+END_SRC
290         *nor*
291         #+BEGIN_SRC C++
292         const Foam::longReturnTypeName& Foam::longClassName::
293         longFunctionName const
294         #+END_SRC
295       + if it needs to be split again, split at the function name (leaving
296         behind the preceding scoping =::=s), and again, left align, i.e.
297         #+BEGIN_SRC C++
298         const Foam::longReturnTypeName&
299         Foam::veryveryveryverylongClassName::
300         veryveryveryverylongFunctionName const
301         #+END_SRC
303 ***** Splitting long lines at an "="
304      Indent after split
305      #+BEGIN_SRC C++
306      variableName =
307          longClassName.longFunctionName(longArgument);
308      #+END_SRC
309      OR (where necessary)
310      #+BEGIN_SRC C++
311      variableName =
312          longClassName.longFunctionName
313          (
314              longArgument1,
315              longArgument2
316          );
317      #+END_SRC
318      *not*
319      #+BEGIN_SRC C++
320      variableName =
321      longClassName.longFunctionName(longArgument);
322      #+END_SRC
323      *nor*
324      #+BEGIN_SRC C++
325      variableName = longClassName.longFunctionName
326      (
327          longArgument1,
328          longArgument2
329      );
330      #+END_SRC
332 *** Maths and Logic
333     + operator spacing
334       #+BEGIN_SRC C++
335       a + b, a - b
336       a*b, a/b
337       a & b, a ^ b
338       a = b, a != b
339       a < b, a > b, a >= b, a <= b
340       a || b, a && b
341       #+END_SRC
343     + splitting formulae over several lines
345       Split and indent as per "splitting long lines at an ="
346       with the operator on the lower line.  Align operator so that first
347       variable, function or bracket on the next line is 4 spaces indented i.e.
348       #+BEGIN_SRC C++
349       variableName =
350           a*(a + b)
351          *exp(c/d)
352          *(k + t);
353       #+END_SRC
354       This is sometimes more legible when surrounded by extra parentheses:
356       #+BEGIN_SRC C++
357       variableName =
358       (
359           a*(a + b)
360          *exp(c/d)
361          *(k + t)
362       );
363       #+END_SRC
365     + splitting logical tests over several lines
367       outdent the operator so that the next variable to test is aligned with
368       the four space indentation, i.e.
369       #+BEGIN_SRC C++
370       if
371       (
372           a == true
373        && b == c
374       )
375       #+END_SRC
377 ** Documentation
378 *** General
379     + For readability in the comment blocks, certain tags are used that are
380       translated by pre-filtering the file before sending it to Doxygen.
382     + The tags start in column 1, the contents follow on the next lines and
383       indented by 4 spaces. The filter removes the leading 4 spaces from the
384       following lines until the next tag that starts in column 1.
386     + The 'Class' and 'Description' tags are the most important ones.
388     + The first paragraph following the 'Description' will be used for the
389       brief description, the remaining paragraphs become the detailed
390       description.
392       For example,
393       #+BEGIN_SRC C++
394       Class
395           Foam::myClass
397       Description
398           A class for specifying the documentation style.
400           The class is implemented as a set of recommendations that may
401           sometimes be useful.
402       #+END_SRC
404     + The class name must be qualified by its namespace, otherwise Doxygen
405       will think you are documenting some other class.
407     + If you don't have anything to say about the class (at the moment), use
408       the namespace-qualified class name for the description. This aids with
409       finding these under-documented classes later.
410       #+BEGIN_SRC C++
411       Class
412           Foam::myUnderDocumentedClass
414       Description
415           Foam::myUnderDocumentedClass
416       #+END_SRC
418     + Use 'Class' and 'Namespace' tags in the header files.
419       The Description block then applies to documenting the class.
421     + Use 'InClass' and 'InNamespace' in the source files.
422       The Description block then applies to documenting the file itself.
423       #+BEGIN_SRC C++
424       InClass
425           Foam::myClass
427       Description
428           Implements the read and writing of files.
429       #+END_SRC
431 *** Doxygen Special Commands
432     Doxygen has a large number of special commands with a =\= prefix.
434     Since the filtering removes the leading spaces within the blocks, the
435     Doxygen commmands can be inserted within the block without problems.
436     #+BEGIN_SRC C++
437     InClass
438         Foam::myClass
440     Description
441         Implements the read and writing of files.
443         An example input file:
444         \verbatim
445             patchName
446             {
447                 type        myPatchType;
448                 refValue    100;
449                 value       uniform 1;
450             }
451         \endverbatim
453         Within the implementation, a loop over all patches is done:
454         \code
455             forAll(patches, patchI)
456             {
457                 ...  // some operation
458             }
459         \endcode
460     #+END_SRC
462 *** HTML Special Commands
463     Since Doxygen also handles HTML tags to a certain extent, the angle
464     brackets need quoting in the documentation blocks. Non-HTML tags cause
465     Doxygen to complain, but seem to work anyhow.
467     eg,
468     + The template with type =<HR>= is a bad example.
469     + The template with type =\<HR\>= is a better example.
470     + The template with type =<Type>= causes Doxygen to complain about an
471       unknown html type, but it seems to work okay anyhow.
473 *** Documenting Namespaces
474     + If namespaces are explictly declared with the =Namespace()= macro,
475       they should be documented there.
477     + If the namespaces is used to hold sub-models, the namespace can be
478       documented in the same file as the class with the model selector.
479       eg,
480       #+BEGIN_SRC C++
481       documented namespace 'Foam::functionEntries' within the
482       class 'Foam::functionEntry'
483       #+END_SRC
485     + If nothing else helps, find some sensible header.
486       eg,
487       #+BEGIN_SRC C++
488       namespace 'Foam' is documented in the foamVersion.H file
489       #+END_SRC
491 *** Documenting typedefs and classes defined via macros
492     ... not yet properly resolved
494 *** Documenting Applications
495     Any number of classes might be defined by a particular application, but
496     these classes will not, however, be available to other parts of
497     OpenFOAM. At the moment, the sole purpuse for running Doxygen on the
498     applications is to extract program usage information for the '-doc'
499     option.
501     The documentation for a particular application is normally contained
502     within the first comment block in a /.C/ source file. The solution is this
503     to invoke a special filter for the "/applications/{solver,utilities}/"
504     directories that only allows the initial comment block for the /.C/ files
505     through.
507     The layout of the application documentation has not yet been finalized,
508     but foamToVTK shows an initial attempt.
510 *** Orthography
511     Given the origins of OpenFOAM, the British spellings (eg, neighbour and not
512     neighbor) are generally favoured.
514     Both '-ize' and the '-ise' variant are found in the code comments. If
515     used as a variable or class method name, it is probably better to use
516     '-ize', which is considered the main form by the Oxford University
517     Press. Eg,
518     #+BEGIN_SRC C++
519     myClass.initialize()
520     #+END_SRC
522     The word "its" (possesive) vs. "it's" (colloquial for "it is" or "it has")
523     seems to confuse non-native (and some native) English speakers.
524     It is better to donate the extra keystrokes and write "it is" or "it has".
525     Any remaining "it's" are likely an incorrect spelling of "its".