Here we define the style conventions used in Pastel.
Write programs and documentation to be read by others.
Maximize readability of the code in English.
Use English everywhere. Most computer-related terms have their roots in English and are well known, while their translations in other languages are probable to be less known and thus hard to decipher.
Code: pastel/
Sub-library: pastel/sub/
Sub-library import: pastel/pastelsub.h
Module: pastel/sub/module/
Module code: pastel/sub/module/code.h
Module import: pastel/sub/module.h
An aggregate file pastel/sub/aggregate.h
A class is a module.
A concept is a module. Example: pastel/sys/input/
A collection of tightly related concepts is a module. Example: pastel/sys/algebra/
.
A collection of algorithms solving the same problem with different kinds of things is a module. Example: pastel/geometry/distance/
.
Test code: test/
Testing for a sub-library: pastel/sub/
A sub-library pastel/sub/
contains a documentation file pastel/sub/pastelsub.txt
.
A module pastel/sub/module/
contains a documentation file pastel/sub/module/module.txt
.
A module pastel/sub/module/
has a module import file pastel/sub/module.h
.
Types: LikeThis
Public namespaces: LikeThis
Private namespaces: LikeThis_
Macros: PASTEL_LIKE_THIS
Functions, variables: likeThis
Program-time constants: LikeThis
. A program-time constant is a variable identifier whose value stays the same no matter when the value is considered during the program run. For example: const real ShortPi = 3.14;
. This includes compile-time constants, such as enumerations. In particular, program-time constants are not named with upper-case characters with underscore delimiters, because they would then risk colliding with macros.
Scope-time constants: likeThis
. A scope-time constant is an object identifier whose value stays the same from its construction to its destruction but can not be guaranteed to be the same at all times during the program run. For example: const integer width = image.width();
. In particular, scope-time constants are named just like normal variables.
Class member variables: likeThis_
. This convention avoids naming conflicts between function parameters, the member variables of a class, and the getters of member variables.
Template parameters: LikeThis_
. This convention avoids naming conflicts between template parameters, class member types, and class member constants.
Class static variables: likeThis__
Files: intersect_alignedbox_alignedbox.h
Directories: pastel/sys/
Libraries: PastelSys
Header file guards: PASTELSYS_LIKETHIS_H
Setters: setRadius()
Getters: radius()
Boolean getters: empty()
. In particular, the is
prefix is not used. Exception: is
prefix can be used for disambiguation if the property can be interpreted both as a verb and an adjective. For example: open
as isOpen
Collections: shapeSet
. In particular, the plural shapes
is not used, because it collides with quantities. In addition, more detailed suffixes such as Array
or List
are not used. This allows to change the type of the container easily, say, when it is noticed during development that a list is needed instead of an array.
Quantities: shapes
, leaves
.
Derived classes of an abstract class: LikeThis_BaseClass
. For example, if Filter
is an abstract class, then Gaussian_Filter
could be one of its derived classes.
A class modeling a concept: ClassName_ConceptName
. For example, if NormBijection
is a concept, then Euclidean_NormBijection
could be one of its models.
When using the Curiously Recurring Template Pattern with the class MyClass
, name the super class MyClass_Base
All control structures must have their actions defined on a block.
Place { and } on individual rows.
Write at most one statement per row.
One row, one logical operation. It is hard to follow things
such as a = b = c++;
.
Pass in-parameter native types by value.
Pass in-parameter objects by const reference.
Use word that
in member functions to mean an object of the same class.
Use word result
to store the return value of a function if there is
no better name.
Write a space after a comma: a, b, c
Separate binary operators with spaces from both sides: a + b, a - b, a = b, a * b, a / b, a % b, a b
, …
In a switch structure, if one case is meant to slip through to the handler of the next case, comment it with a Fall-through
.
Use using
-aliases instead of typedef
-aliases. This provides better readability.
If relational operators are needed (<
, >
, <=
, >=
), implement less-than and implement the rest of the operators in terms of that.
If equality operators are needed (==
, !=
), implement equality and implement non-equality in terms of that.
If increment operators are needed (pre- and post-fix), implement prefix increment and implement postfix increment in terms of that. Similarly for decrement.
Use the boost::operators
library to accomplish these in an easy way.
Do not attempt to align for any other condition than indentation. In particular, do not place comments after a statement. The position of the comment changes with the length of the statement before it and thus changing the statement requires to reposition the comment. The comment is also likely to exceed the given maximum of 70 characters per row.
Use hard tabs for indentation and only for indentation. Desired indentation amount is dependent on the programmer. Tabs make it possible to change it on the fly without modifying the source code. The problems with the tabs stem from the fact that it is often used incorrectly to match other boundary conditions than indentation (in the middle of a statement).
A hard tab can be added only if preceded by another hard tab or the beginning of a row.
For source code, limit the width of lines by manual line-breaks to a maximum of 70 characters. This is because the text editors in some IDEs (e.g. Visual Studio 2012) do not respect indentation on word-wrapping, which destructs the logical structure of the code. Moreover, using the IDE’s text editor can not be avoided because compiling (fixing compilation errors) and debugging (fixing runtime errors) requires it. The 70 character limit is because readability requires text to cover a narrow width.
For documentation, use manual line-breaks for structure (e.g. paragraphs) and only for structure. In particular, do not use manual line-breaks to achieve a narrow representation. Instead, rely on the word-wrapping of the text viewer for an adaptive width. The difference to the source code is that here one is not bound to the IDE’s text editor.
Class definition (function declaration) files: .h
Non-template function definition files: .cpp
Template/inline function definition files: .hpp
Forward-declaration type files: like_this_fwd.h
.
Include the .hpp file in its corresponding .h file.
Include the .h file in its corresponding .hpp file.