=====Coding standard===== ==== Naming conventions ==== The names of classes, attributes, services, variables, and functions in a program serve as comments of a sort. So don't choose terse names--instead, look for names that give useful information about the meaning of the variable or function. In a OOFEM program, names should be English, like other comments. Local variable names can be shorter, because they are used only within one context, where (presumably) comments explain their purpose. Try to limit your use of abbreviations in symbol names. It is ok to make a few abbreviations, explain what they mean, and then use them frequently, but don't use lots of obscure abbreviations. Please use capital letters to separate words in a name. Stick to lower case; reserve upper case for macros, and for name-prefixes that follow a uniform convention. The function or service name should always begin with lovercase letter, the first uppercase letter in function name indicates, that function is returning newly allocated pointer, which has to be dealocated. For example, you should use names like ignoreSpaceChangeFlag; When you want to define names with constant integer values, use enum rather than `\#define'. GDB knows about enumeration constants. Use descriptive file names. The class declarations should be placed in *.h files and class implementation in corresponding *.C files. For each class, create a separate files. ==== Parameters and return values ==== The preferred argument passing method for objects is by reference. Try to avoid returning pointers to arrays or matrices (or generally to any component), since it is not clear, whether to dealocate the returned pointer or not. The most preferred way is to create local variable of vector or matrix type, pass it (using reference) to called function. The calling function is responsible to properly resize the (output) parameter and set values accordingly. The point is, that destructors are called for local variables automatically by compiler, so there is no possibility for memory leaks and the local variable can be reused for multiple calls to target function (inside loop) and therefore there is no need for repeating memory allocation and deallocation. ==== Using comments to document the code ==== OOFEM uses [[http://www.stack.nl/~dimitri/doxygen/|Doxygen]] documentation system to automatically generate the reference manual directly from the OOFEM header files. By placing comments in a few strategic places a complete reference manual, including graphics, can be generated. You will typically want to do so for your header files only. If you are overloading methods from another class, you should **leave the documentation empty** and make sure the parameters are named exactly the same. Only write a new documentation field if you have something new to add specifically to the implemented methods. In general, a special comments should be added straight before each function, variable, class, define, etc. you wish to document. The simplest way is to add a simple comment with a short documentation string for the entry, e.g.: /// Array storing nodal coordinates. FloatArray coordinates; /// Description of enumeration enum SomeEnum { SE_First, ///< Description of first. SE_Second, ///< Description of second. SE_Third, ///< Description of third. } If you intend to write more than one line of documentation, succeed this line with a comment like %%/** .... */%% and put the long documentation text in place of ``...''. For example: /** * Triplet defining the local coordinate system in node. * Value at position (i,j) represents angle between e'(i) and e(j), * where e' is base vector of local coordinate system and e is * base vector of global c.s. */ FloatMatrix localCoordinateSystem; Doxygen automatically imposes a hierarchical stucture to the manual entries for classes, structs, unions, enums and interfaces, in that it organizes members of such as sub-entries. If you need to group manual entries, you may do so with the construction: /** * @name * */ ///@{ ///@} This will create an entry with the specified name, that contains all as sub entries. Note, however, that class members are automatically set as sub entries of the class's manual entry. To document a function or a method of a class, describe the working and usage of the member function, as well as the individual parameters and return values. For example: /** * Class implementing node in finite element mesh. Node posses degrees of freedom. * Node is atribute of few elements and it is managed by domain. * Node manages its positon in space, and optional local coordinate system. * By default, global coordinate system is assumed in each node. */ class Node : public DofManager { public: /** * Computes the load vector of receiver in given time. * @param answer Load vector. * @param stepN Time step when answer is computed. * @param mode Determines response mode. */ virtual void computeLoadVectorAt(FloatArray &answer, TimeStep *stepN, ValueModeType mode); } Again, Doxygen will inherit documentation from super classes, so do not add comments unless something specific needs to be said for the implementing routine. Be sure to document all variables and return value, even trivial ones, to avoid reporting errors when generating the documentation. Currently, OOFEM contains quite a large number of errors in the documentation and a convenient way to list all these errors is to separate the stderr output with the terminal command; doxygen doc/refman/doxygen.cfg 2> dox_errors.txt === Header file layout === Each header file has the following layout: * Copyright notice * Inclusion protection macro * Headers file includes * Forward declarations * Actual class definition with doxygen comments For a typical example see element.h. Each implementation file has the following layout: * Copyright notice * Header file includes * Actual method implementation For a typical example see element.C ==== Indentation & formatting ==== Coding style is very personal and we don't want to force our views on anybody. But for any contributions to the OOFEM system that we have to maintain we would like you to follow our coding style and common formatting. We ask all contributors to use [[http://uncrustify.sourceforge.net/|Uncrustify]] (Source Code Beautifier) to reformat the code according to our defaults. We provide the uncrustify config file (located in top oofem directory). To run uncrustify on a selected file, use uncrustify -c oofem_dir/uncrustify.cfg --replace mysource.C ===== Documentation and Testing ===== OOFEM aims to be high quality software and as a such it must be accompanied by high quality, up to date documentation. Also internal tests and benchmarks are absolutely necessary to ensure continuous software quality . * The new functionality (elements, material models, etc.) will be only accepted if relevant documentation will be provided, in particular the oofem manuals should describe the new functionality * The new functionality will be only accepted if internal tests will be developed and documented. See existing tests in oofem distribution (tests directory), and [[http://www.oofem.org/resources/doc/extractorInput/html/extractorInput.html|Extractor Specification]] ===== Checks before committing ===== * For new work, commit only when some stage of implementation is reached and code is already useful. Do not use svn repository as daily backup tool for your files, that you are developing for several weeks. * Test your implementation before committing. Run at least oofem basic tests and check the results: cd targets/your_target_name; make tests less test_results * Check if documentation is updated as well (includes not only doc++ comments, but also oofem documentation, that can be affected). Making it later usually means never. * Make sure that new functionality comes with internal tests. * Please compile your sources with "-Wall", which will enable all the compiler warnings. Check compiler messages and clean up the code. * Reformat your code using uncrustify tool