-
Notifications
You must be signed in to change notification settings - Fork 178
Coding style
Petr Ohlídal edited this page Oct 22, 2019
·
3 revisions
Discuss here: https://github.com/RigsOfRods/rigs-of-rods/issues/839
- Variable style:
some_variable
. - Function style
SomeFunction()
(CamelCase without underscores). Functions starting with 'Set/Get/Has/Was/Is' are getters/setters - keep them simple. -
class
orstruct
style: CamelCase.typedef struct
is forbidden (meaningless in C++). -
enum
style name is CamelCase, enum members are UPPERCASE_WITH_UNDERSCORES.typedef enum
is forbidden (meaningless in C++). -
using
directives are forbidden in headers and generally discouraged. Use explict namespace qualifiers. -
inline
is forbidden except for global functions defined in header files (for sanity - member functions in headers are implicitly inline). - C++ standard RTTI is forbidden. If you really need it (we're not a library, why use complex class hierarchies internally?), create a custom one like LLVM style RTTI
- Singleton pattern is forbidden. We're not making a library. Use plain objects in static memory.
- Memory management rule#1: If you know the object/data size, use static or stack memory. Don't allocate dynamically without a good reason.
- Memory management rule#2: If rule#1 cannot apply, employ the RAII pattern: use a
std::unique_ptr
to manage the memory. Only usestd::shared_ptr
if there is actual shared ownership! - When calling class methods, always use explicit
this->
, to distinguish methods from global functions. - Only do bare minimum of work in constructors and destructors. For complex inits, use factory functions.
- Exception specifications (i.e. 'throws()') are forbidden. Read http://www.gotw.ca/publications/mill22.htm
- Use 4 spaces for both indentation and alignment. Tabs are forbidden.
- For pointers, only
nullptr
is allowed as empty value - never use0
orNULL
- Always use
{}
withif()
and loops, to avoid bugs like this. - Name
bool
variables using short yes/no question, for examplem_is_initialized
instead ofm_initialized
. - Properties are obfuscated getter/setter functions, don't mimick them in C++.
- use Doxygen tags
///
and//!<
to document the sources.
Header:
/* //STYLE: License block
This source file is part of Rigs of Rods
Copyright 2005-2012 Pierre-Michel Ricordel
Copyright 2007-2012 Thomas Fischer
Copyright 2013-2016 Petr Ohlidal
For more information, see http://www.rigsofrods.com/
Rigs of Rods is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
Rigs of Rods is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
*/
/**
@file CodingStyleTemplate.h
@brief Wiki coding style template
@author CrazyTrucker
@date 05/2014
*/
//STYLE: blank line!
#pragma once //STYLE: header guard (we don't use header guard macros anymore)
//STYLE: blank line!
#include "RoRPrerequisites.h" //STYLE: RoR includes.
#include "BeamData.h" // Try minimizing the dependencies between headers
#include "Flexable.h" // Take advantage of forward declarations
#include "MaterialFunctionMapper.h"
//STYLE: blank line!
#include <OgreVector3.h> //STYLE: External includes
#include <OgreQuaternion.h> // Again, try minimizing the dependencies between headers
#include <OgreHardwareVertexBuffer.h> // Including individual OGRE headers is preferred to including Ogre.h
#include <OgreMesh.h>
//STYLE: blank line!
namespace CodingTemplate //STYLE: Namespace
{ // NOTE: No indentation in namespace!
/// Brief description (must be ended with dot).
/// Detailed description.
struct CodingStyleDemoStruct
{ //STYLE: { on new line.
CodingStyleDemoStruct(): //STYLE: Initializing constructor.
struct_member_variable(0),
another_member_variable(0.f)
{}
//STYLE: blank line!
int struct_member_variable; //!< Description //STYLE: variables and documentation. Mind the alignment.
float another_member_variable; //!< Description
};
/// Brief description (must be ended with dot). //STYLE: Class, inheritance
/// Detailed description. // **REMEMBER!** Public inheritance means **IS-A!**
class CodingStyleDemoClass: public BaseDemoClass // "class B: public A" means "B is also A" !!
{
//STYLE: blank line before member struct!
/// Just for little cleaner code...
struct MemberStructure //STYLE: member struct
{
SubStructure(int stuff) //STYLE: Parametrized constructor
stuff(stuff)
{}
int stuff;
};
//STYLE: blank line!
public:
//STYLE: blank line!
CodingStyleDemoClass():
m_private_member_variable(0),
m_another_private_variable(0.f),
m_example_pointer(nullptr), //STYLE: use 'nullptr' keyword for NULL pointers
m_example_calculator(nullptr)
{}
//STYLE: blank line!
enum PossibleOptions //STYLE: enum
{
OPTION_BEGIN //STYLE: special option
OPTION_FOO //!< Description //STYLE: all options have equal prefix
OPTION_BAR //!< Description
OPTION_BAZ //!< Description
OPTION_END //STYLE: special option
OPTION_INVALID = 0xFFFFFFFF //STYLE: special option and value
};
static const unsigned int DEPOT_SERVICE = BITMASK(1); //STYLE: bit flags
static const unsigned int DEPOT_MASS_SEND = BITMASK(2); // Use BITMASK() from RoRPrerequisites.h
static const unsigned int DEPOT_DONT_CANCEL = BITMASK(3); // Do NOT use enums for bitflags
static const unsigned int DEPOT_LOCATE_HANGAR = BITMASK(4); // because it blocks using | operator
//STYLE: blank line!
//STYLE: blank line!
public:
//STYLE: blank line!
char public_member; //STYLE: public member
//STYLE: blank line!
int GetPrivateMemberVariable() //STYLE: function (getter)
{
return m_private_member_variable; //STYLE: Don't use {{this->}} to access members
}
/// Returns highest number
int FunctionWithManyArguments( //STYLE: Functions with too long argument list
int first_argument, // ... will be split to multiple lines.
int second_argument,
int third_argument,
int fourth_argument, // NOTE: Define your functions in .cpp files
int fifth_argument, // ... to decrease compile dependencies!
int last_argument // One-line getters (as above) are fine though.
);
int GetMemberValue() { return m_private_member_variable; } //STYLE: Getter function -> `Get` in name
int ComputeHighestNumberUsingBranches(int a, int b, int c); //STYLE: Not a getter -> no `Get` in name
int ComputeHighestNumberUsingConditionals(int a, int b, int c, int d, int e, int f);
int AddNumbers(int a, int b);
bool IsPointerNotNull(); //STYLE: A `bool` method is named as yes/no question.
//STYLE: blank line!
private:
//STYLE: privates are prefixed m_. Mind the alignment.
int m_private_member_variable;
float m_another_private_variable;
PointedClass* m_example_pointer; //STYLE: pointer member ~ * at datatype
ExampleCalculator* m_example_calculator;
};
} // namespace CodingTemplate //STYLE: End of namespace.
Source:
//STYLE: blank line!
#include "CodingTemplate.hpp" //STYLE: The associated header on first line.
//STYLE: blank line!
#include "AnotherHeader.hpp" //STYLE: RoR includes.
//STYLE: blank line!
#include "OgreMaterialManager.h" //STYLE: External includes
namespace CodingTemplate //STYLE: Namespace
{ // NOTE: No indentation in namespace!
int CodingStyleDemoClass::FunctionWithManyArguments( //STYLE: Functions with too long argument list
int first_argument, // ... will be split to multiple lines.
int second_argument,
int third_argument,
int fourth_argument,
int fifth_argument,
int last_argument
)
{
int a = this->GetHighestNumberUsingBranches( // STYLE: using explicit this->
first_argument, // to distinguis member functions
second_argument, // and global functions
third_argument
);
int b = this->GetHighestNumberUsingBranches( // STYLE: Explicit this->
fourth_argument,
fifth_argument,
last_argument
);
return (a > b) ? a : b;
}
int CodingStyleDemoClass:::ComputeHighestNumberUsingBranches(int a, int b, int c)
{
if (a < b) //STYLE: if() statements
{ // {} must always be present
if (b < c) // {} must always be on new line
{ // NOTE: Always consider using conditionals (below)
return c;
}
else
{
return b;
}
}
else
{
if (a < c)
{
return c;
}
else
{
return a;
}
}
}
int CodingStyleDemoClass::ComputeHighestNumberUsingConditionals(int a, int b, int c, int d, int e, int f)
{
int highest = (a > b) ? a : b; //STYLE: conditional assignments
highest = (highest > c) ? highest : c; // Use them! :)
highest = (highest > d) ? highest : d;
highest = (highest > e) ? highest : e;
return (highest > f) ? highest : f;
}
bool CodingStyleDemoClass::IsPointerNotNull()
{ //STYLE: NULL pointer test
return (m_example_calculator != nullptr) // Using {{if (pointer)}} conditions is forbidden
{ // ... only bools can be tested this way.
int CodingStyleDemoClass::AddNumbers(int a, int b)
{
assert (m_example_calculator != nullptr); //STYLE: NULL pointer debug test
return m_example_calculator->Add(a, b); //STYLE: Don't use {{this->}} to access members
}
} // namespace CodingTemplate //STYLE: End of namespace.