Hermes Programming Style
-
I. DO NOT use C-style variables
-
example: a varible 'i' is declared at the beginning of the function and used in multiple for-loops inside the function
-
replacement: declare the variable when you use it
description: This improves readability of the code because Hermes2d does not follow any naming scheme in this case.
Hence, this clearly indicates which variables might carry information outside the loops and which variables just
control the loop. Among others, it helps to avoid copy & paste errors in which the same variable is used to control
both the inner and the outer loop.
II. DO try to match type of integers
-
example: 'for(i = 0; i < bfvol.size(); i++)' where 'i' is declared as 'int i;'
-
replacement: 'for(unsigned int i = 0; i < bfvol.size(); i++)'
-
description: This prevents a warning about incompatibility between a signed integer and an unsigned integer. The warning can be disable\
d but it is better to avoid it through a proper type.
III. DO NOT use names without a prefix for preprocessor directives
-
example: 'DOMAIN' (bessel.cpp, collides with a directive defined in math.h)
-
replacement: 'H2DSETUP_DOMAIN'
-
description: This prevents redefinition warning.
-
note: Similarly, a directive 'ERROR_SUCCESS'. which is defined in all examples,
redefines a directive defined in 'windows.h'.
IV. DO remove unreferenced variables
-
example: several variables are not used but still they are declared
-
replacement: remove a variable when a code which uses it was removed
-
description: This avoids warnings and improves readibility of the code.
V. DO return a value from a function if the function declares a return type
-
description: This avoids a warning and it makes the code safer.
If at the if-branching inside such a function receives erroneous input,
the function will return a predefined invalid value rather than some
compiler-specific value.
VI. DO NOT use variable-length arrays (VLA)
-
example: 'AsmList al[wf->neg];'
-
replacement: 'AUTOLA_CL(AsmList, al, wf->neq);'
-
note: If the type is not a class or a structure, a macro 'AUTOLA_OR' can be used instead. This macro does not call constructor and therefore it may allocate the data on stack.
-
descrition: Variable-length arrays are introduced in C99 which is *not* part of ISO C++. Therefore, MSVC does not support it. Also, the stack has only a limited size and therefore it should not be used similar to the heap.
VII. DO explicitly declare types of constants
-
example: 'sqrt(2)'
-
replacement: 'sqrt(2.0)'
-
descrition: Since C++ allows overloading and the function SQRT has at least two overloads which both allow a valid conversion from an integer. Hence, the compiler might not be able to select between these two.
VIII. DO use the macro 'EXTERN' when declaring a public variable, i.e., a variable which is part of API
-
example: 'extern int g_max_order;'
-
replacement: 'EXTERN int g_max_order;'
-
descrition: In MSVC, Hermes2d is compiled into a DLL. Windows DLL is a stand-alone module which behaves differently from SO on LINUX. All exported symbols has to be explicitly marked by '__declspec(dllexport)' and all imported symbols has to be explicitly marked by '__declspec(dllimport)'. The macro 'EXTERN' does this for you. Please, use it.
IX. DO use the macro 'EXTERN' and 'PUBLIC_API' when declaring a public function, i.e., a function which is part of API
-
example:
# declaration: 'extern void warn_order();'
# definition: 'void warn_order() {...'
-
replacement:
# declaration: 'EXTERN void warn_order();'
# definition: 'PUBLIC_API void warn_order() {...'
descrition: This is similar to the macro 'EXTERN'.
X. DO use the macro 'PUBLIC_API' when declaring a public class which is not a template.
-
example: 'class LinSystem'
-
replacement: 'class PUBLIC_API LinSystem'
-
descrition: This is similar to the macro 'EXTERN'.