StyleGuide
This is the coding style guide to be used for all code of the TheLib project.
The coding style guide Crowbar28 was defined based on its predecessor Crowbar27 with the goal to better blend with STL code.
While this guide focusses on C++ files it must also be applied to all other file types as precisely as possible.
In doubt, first look at the existing code if there already is a similar case of your current situation in TheLib and then use the same solution.
Only if not, then use common sense and try to write code following the spirit of this style guide.
Contents |
Capitalization
There are four capitalization types possible:
- Pascal Case: e.g. GetCurrentTime, Abbreviations of only two letters are capitalized, e.g. IO, while longer abbreviations are handles like a normal word, e.g. Xml or Gui.
- lower Camel Case: Similar to camel case but always starting with a lower case character, e.g. fullPrecision.
- Uppercase: Only uses upper case characters and separates words with underscores "_", e.g. SOME_COMPILE_TIME_DEFINITION.
- Lowercase: The same as uppercase but with lower case characters, e.g. this_is_the_default.
Rules:
Uppercase is used for
- Macros
- Defines
Lowercase is used for
- namespaces
- classes and structs
- types
- class members and methods, regardless of their visiblity
- enum values
lower Camel Case can be used for
- private class members, especially fields
- function/method parameters
Pascal Case is used for
- Template parameters
Rule Exceptions
- Names, e.g. type/function/method names, with a prefix or suffix at one of their words, like a short abbreviation or the letter 't', as indication for
tcharusage, can use for that word lower Camel Case (e.g.formatVa) or can omit the underscore between the word an the abbrevation (e.g.astring,wstring,tstring)
Common Information
- Source code files use the extension ".cpp"
- Header files use the extension ".h"
- Each cpp/h file pair contains exactly one class (except further nested classes or template specializations) and both files and the class have the identical name.
- The subdirectories of the cpp/h files correspond exactly to the namespace the class is placed in.
- Ordering of members of a class is as follows:
- First, sorted by visibility: first public, then protected, at last private.
- Second, sorted by type: first static fields, then static methods, then instance fields, then instance methods.
- Third, sorted by name, alphabetically.
- Avoid implicit inlining.
- Use include guards like shown in the example below.
- All files end with a line break.
- Do not mix Dos- and Unix line breaks in one file.
- When accessing instance members from within a class, always preceed with "this->" (e.g. "j = i + this->stepSize;" ).
- When accessing static members from within a class, always preceed with the class name (e.g. "j = i + my_class::default_step_size;" ).
- "friend" declarations are written as first or as last entries within a class definition.
Enums
Enums must use the new C++11 syntax:
enum class color { yellow, orange, red };
// specifying the underlying type for new enums
enum class fruit : uint16_t { apple, pear, orange };
It is then used accordingly including the enum type name:
name::space::color col = name::space::color::orange
config.h
The file "the/config.h" controls the configuration of TheLib and must thus be included as first file in all header files of TheLib:
#include "the/config.h"
Stack Trace
TheLib uses as debugging stack trace implementation.
Thus each file needs to #include "the/stack_trace.h" and use the THE_STACK_TRACE; macro at the beginning of every method!
See the example below for an ... example.
Formatting
- The opening braces "{" are not placed on a new line.
- "else" is placed on the same line as the closing brace.
- Indention uses four spaces, not tabs.
- Do not use hungarian notation for variables.
- Comment lines are wrapped after at most 79 characters.
- Use common sense to find suitable positions to wrap long lines.
- If a parameter list needs to be wrapped, it is indented twice (i.e. eight spaces) to be visually separated from following code lines.
- Function declarations are separated by exactly one blank line.
- Function definitions are separated by two blank lines and a function definition header comment.
Naming
Methods
All methods returning parts of the internal state of an object should begin with the verb "get_".
Methods querying a state information of an object and returning a boolean value should begin with "is_" or "has_".
All methods primarily changing parts of the internal state of an object without triggering too large computations begin with the verb "set_".
Especially Getter and Setter method pairs must conform to these naming rules.
Commentation
- All class and function declarations are commented with doxygen comment blocks.
/** * This is a demo function * * @param a A value * * @return Another value */ int demo_function(int a);
- in C# code use Xml comments instead of doxygen.
- Function definitions are preceeded by a three-line comment block repeating the full function name:
/*
* name::space::class::some_function
*/
int name::space::class::some_function(int parameter) {
- Comments must state limitations and assumptions of the function/class.
- "#end", "#else", and closing braces can be followed by a block comment repeating information from the corresponding opening element (e.g. "#if"). See example below.
File Header Comment
Each file must start with the following header comment:
/* * dir/filename.ext * * Copyright (c) 2012, TheLib Team (http://www.thelib.org/license) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of TheLib, TheLib Team, nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THELIB TEAM AS IS AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THELIB TEAM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
The file name must be in exact spelling without paths.
The date "2012" at the _THELib Team_ Copyright line are the years of the first and the last change of this file
Optional copyright lines may follow, if the file was originally created by someone else. These lines may be formatted differently.
After the copyright lines, the license is stated as shown above.
Include Guards
The following include guards must be used in all Header files directly following the header comment block:
#ifndef FILE_NAME_WITH_PATH_H_INCLUDED #define FILE_NAME_WITH_PATH_H_INCLUDED #if (defined(_MSC_VER) && (_MSC_VER > 1000)) #pragma once #endif /* (defined(_MSC_VER) && (_MSC_VER > 1000)) */ #if defined(_WIN32) && defined(_MANAGED) #pragma managed(push, off) #endif /* defined(_WIN32) && defined(_MANAGED) */
File Content
#if defined(_WIN32) && defined(_MANAGED) #pragma managed(pop) #endif /* defined(_WIN32) && defined(_MANAGED) */ #endif /* FILE_NAME_WITH_PATH_H_INCLUDED */
The Macro FILE_NAME_WITH_PATH_H_INCLUDED is to be replaced with the file name, including file name extension and path (the portion after the include folder), written in upper case.
Example
demo_class.h:
/* * the/demo/demo_class.h * * Copyright (c) 2012, TheLib Team (http://www.thelib.org/license) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of TheLib, TheLib Team, nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THELIB TEAM AS IS AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THELIB TEAM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef THE_DEMO_DEMO_CLASS_H_INCLUDED #define THE_DEMO_DEMO_CLASS_H_INCLUDED #if (defined(_MSC_VER) && (_MSC_VER > 1000)) #pragma once #endif /* (defined(_MSC_VER) && (_MSC_VER > 1000)) */ #if defined(_WIN32) && defined(_MANAGED) #pragma managed(push, off) #endif /* defined(_WIN32) && defined(_MANAGED) */ #include "the/config.h" namespace the { namespace demo { /** * Demo class demonstrating correctly styled source code */ class demo_class { public: /** * A demo function * * @param i A integer value * * @return 'i' incremented by the increment step */ int demo_function(int i); private: /** The increment step */ static int incStep; }; } /* end namespace demo */ } /* end namespace the */ #if defined(_WIN32) && defined(_MANAGED) #pragma managed(pop) #endif /* defined(_WIN32) && defined(_MANAGED) */ #endif /* THE_DEMO_DEMO_CLASS_H_INCLUDED */
demo_class.cpp:
/* * the/demo/demo_class.cpp * * Copyright (c) 2012, TheLib Team (http://www.thelib.org/license) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of TheLib, TheLib Team, nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THELIB TEAM AS IS AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THELIB TEAM BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "the/demo/demo_class.h" #include "the/stack_trace.h" /* * the::demo::demo_class::demo_function */ int the::demo::demo_class::demo_function(int i) { THE_STACK_TRACE; return i + demo_class::incStep; } /* * the::demo::demo_class::incStep */ int the::demo::demo_class::incStep = 42;