-
-
Notifications
You must be signed in to change notification settings - Fork 11
Codestyle
Vladlen edited this page Feb 16, 2021
·
5 revisions
-
-
- All names should be written in English.
- Use names that describe the purpose or intent of the object
- Name lengths should be proportional to the length of the name's scope
- Optimize for readability using names that would be clear even to people on a different team
- Minimize the use of abbreviations that would likely be unknown to someone outside your project
- As a rule of thumb, an abbreviation is probably OK if it's listed in Wikipedia
- Do not abbreviate by deleting letters within a word
- Do not worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader
-
-
- Start with a capital letter and have a capital letter for each new word, with no underscores
PascalCase
- Header files should have the extension
.h
- Source files should have the extension
.cpp
MyUsefulClass.h MyUsefulClass.cpp
- Start with a capital letter and have a capital letter for each new word, with no underscores
-
- Should be all lowercase with underscores between words
snake_case
- Can be exceptions like
CMakeLists.txt
etcdownloads.bat build_depends_msvc16_debug.bat CMakeLists.txt README.md
- Should be all lowercase with underscores between words
-
-
- Start with a capital letter and have a capital letter for each new word, with no underscores
PascalCase
- The names of all types — classes, structs, type aliases, and template parameters — have the same naming convention.
class SomeClass; struct SomeStruct; typedef TypedefSomeClass SomeClass;
- Type enum must be named with a leading
E
enum class EHotSpotEventFlag;
- Type struct that describe the data in themselves must be named with
Desc
postfixstruct FontDesc { ConstString fontName; uint32_t fontSize; Color fontColor; };
- Start with a capital letter and have a capital letter for each new word, with no underscores
-
-
- Must be in mixed case starting with lower case
camelCase
String tableName;
- Must be in mixed case starting with lower case
-
- Prefix
m_
for non-static members - Prefix
s_
for static nonconstant membersclass SomeClass { public: static const int32_t MAX_COUNTER; private: static int32_t s_staticCounter; private: int32_t m_someCounter; };
- Prefix
-
- Must be named like ordinary nonmember variables
-
- Must be prefixed by single underscore
int32_t setNumber( int32_t _number );
- Must be prefixed by single underscore
-
-
- In function scope must be named like ordinary variables
const int32_t daysInAWeek = 7;
- In other scope, must be named with all uppercase using underscore to separate words
const int32_t MIN_COUNTER = 0; static const int32_t MAX_COUNTER = 10;
- In function scope must be named like ordinary variables
-
- Must be verbs and written in mixed case starting with lower case
camelCase
- Accessors and mutators must be named with prefix
get/set
following by variable nameclass SomeClass { public: int32_t setNumber( int32_t _number ); void getNumber() const; private: int32_t m_number; }
- Class internal callbacks must be prefixed by single underscore (mvi pattern)
class SomeClass { public: void initialize(); protected: virtual void _onInitialize(); };
- Class non virtual protected/private methods must be sufixed by single underscore
class SomeWindow { public: void setupSomeWindow(); protected: void setupLabels_(); void setupButtons_(); };
- Must be verbs and written in mixed case starting with lower case
-
- Start with a capital letter and have a capital letter for each new word, with no underscores
PascalCase
namespace Mengine { };
- Start with a capital letter and have a capital letter for each new word, with no underscores
-
- They should be named with all capitals and underscores
#define ROUND(x) ... #define PI_ROUNDED 3.0 #define MY_MACRO_THAT_SCARES_SMALL_CHILDREN_AND_ADULTS
- They should be named with all capitals and underscores
-
-
-
- Download environment settings, or copy from Mengine folder
- Import in
Tools
->Import and Export Settings...
- Before merger request, please, do
Ctrl + A
->Alt + R
in your modified files for auto format purpose
-
- Do not add spaces inside
<...>
brackets// bad typedef Vector< String > VectorExample; // good typedef Vector<String> VectorExample;
- Do not add spaces inside
-
-
-
- Include statements must be located at the top of a file only
- Include statements should be grouped and sorted in this order:
#include "Interface/..." #include "Interface/..." #include "Plugins/..." #include "Plugins/..." #include "SomeClass.h" #include "SomeService.h" #include "Engine/..." #include "Kernel/..." #include "Kernel/..." #include "Config/..." #include <dependencies> #include <stl> #include <cstyle.h>
-
- Use
namespace Mengine
by defaultnamespace Mengine { };
- Use
-
- Follow the
fast return
rulevoid SomeClass::computeHeavyEquation() { if( isSomethingWentWrong == true ) { // fast return return; } /* ... */ }
- Compare boolean explicitly with
true/false
void SomeClass::computeHeavyEquation() { // boolean explicitly compared with 'true' if( isSomethingWentWrong == true ) { return; } /* ... */ }
- Add explicit
this
pointer for member function callingvoid SomeClass::computeHeavyEquation() { this->computeFirstEquation(); this->computeSecondEquation(); this->computeThirdEquation(); }
- Add parent class namespace without
this
pointer for overridden functions callingvoid SomeClass::_onIntialize() { // 'Super' is only example, use real parent class name instead Super::_onIntialize(); /* .... */ }
- Use local constants for all not tunable magic numbers
- Move tunable constans to .cpp file scope as constexpr
namespace Mengine { ////////////////////////////////////////////////////////////////////////// // tunable constant in .cpp scope constexpr float WINDOW_RELATIVE_WIDTH = 0.3f; ////////////////////////////////////////////////////////////////////////// void Window::setupWindow() { // not tunable constant in method scope const Char * clearBtnLabel = "Clear"; /* .... */ } };
- Remove complex calculations and function calls from function arguments
void Window::setupWindow() { // bad m_window->setButtonLabel( this->getButtonLabelFromCongfig() ); // good const String & btnLabel = this->getButtonLabelFromCongfig(); m_window->setButtonLabel( btnLabel ); /* .... */ } };
- Use only
nullptr
for pointers instead ofNULL
- Define type alias for templates before using of templates only through
typedef
specifier////////////////////////////////////////////////////////////////////////// typedef Map<String, class SomeClass> MapSomeClasses; typedef Vector<class SomeClass> VectorSomeClasses; //////////////////////////////////////////////////////////////////////////
- Define alias template only through
using
specifier////////////////////////////////////////////////////////////////////////// template<class CharT> using MyString = std::basic_string<CharT, std::char_traits<CharT>>; ////////////////////////////////////////////////////////////////////////// void someFunc() { MyString<char> str; /* ... */ };
- Use
auto
only with local lambdas and in range-basedfor
loopvoid someFunc() { auto someLambda = [](){ /* ... */ }; for( auto && [key, value] : someMap ) { } };
- If func need to return some large object as result pass it as
_out
parameter by const pointervoid someFunc( VectorLargeData * const _out ) { for( ... ) { _out->... } };
- Follow the
-
- Use separator:
//////////////////////////////////////////////////////////////////////////
- Put a separator just before some entity.
// SomeClass.h namespace Mengine { ////////////////////////////////////////////////////////////////////////// class SomeClass { public: SomeClass(); ~SomeClass(); }; };
// SomeClass.cpp namespace Mengine { ////////////////////////////////////////////////////////////////////////// namespace Detail { ////////////////////////////////////////////////////////////////////////// static void serviceMethod() { }; }; ////////////////////////////////////////////////////////////////////////// SomeClass::SomeClass() { }; ////////////////////////////////////////////////////////////////////////// SomeClass::~SomeClass() { }; ////////////////////////////////////////////////////////////////////////// };
- Wrap typedef/define or related typedefs/defines groups with a separator.
namespace Mengine { ////////////////////////////////////////////////////////////////////////// typedef Map<String, class SomeClass> MapSomeClasses; typedef Vector<class SomeClass> VectorSomeClasses; ////////////////////////////////////////////////////////////////////////// class SomeClass : public Factorable { public: SomeClass(); ~SomeClass() override; public: static SomeClass * getInstance(); }; ////////////////////////////////////////////////////////////////////////// typedef IntrusivePtr<SomeClass> SomeClassPtr; ////////////////////////////////////////////////////////////////////////// }; ////////////////////////////////////////////////////////////////////////// #define SOME_SINGLETON (Mengine::SomeClass::getInstance()) //////////////////////////////////////////////////////////////////////////
- Use separator:
-
-
-
#pragma once
-
- Use
namespace Helper
in top of parent namespace for class service functions declarationsnamespace Mengine { ////////////////////////////////////////////////////////////////////////// typedef IntrusivePtr<class Sprite> SpritePtr; ////////////////////////////////////////////////////////////////////////// namespace Helper { ////////////////////////////////////////////////////////////////////////// SpritePtr createSpriteFromFile(...); ////////////////////////////////////////////////////////////////////////// SpritePtr createSpriteFromTexture(...); }; ////////////////////////////////////////////////////////////////////////// class Sprite { /* ... */ }; };
- Use
-
- Should be declared in a header file where the name of the files match the name of the class
- All declarations should be in this order:
constructors
destructor
-
setters|getters
methods -
initializing
methods -
public
virtual/non-virtual methods (class interface) -
protected
virtual/non-virtual methods -
private
virtual/non-virtual methods attributes
- Class must contains constructor/destructor declarations without
= default
or= delete
- All definitions should reside in source files
- Visibility modifier should be used like separator for class member groups
class SomeClass { public: SomeClass(); ~SomeClass(); public: int32_t setNumber( int32_t _number ); void getNumber() const; public: void initialize(); protected: virtual _onIntialize(); private: int32_t m_number; };
- One header - one class declaration
-
-
-
- The first
#include
must contains related header file of this source file - The rest is exactly the same as in General For Source Files
- The first
-
- Use
namespace Detail
in top of parent namespace for service entities/functions which don't go beyond class definition- In
namespace Detail
all functions must bestatic
namespace Mengine { ////////////////////////////////////////////////////////////////////////// namespace Detail { ////////////////////////////////////////////////////////////////////////// static ComputeResult computeSomething() { }; }; };
- In
- Use
-
-
-
- In general the actual name of the variable should be descriptive enough to give a good idea of what the variable is used for
-
- In your implementation you should have comments in tricky, non-obvious, interesting, or important parts of your code
-
- When the meaning of a function argument is nonobvious, consider one of the following remedies:
- If the argument is a literal constant, and the same constant is used in multiple function calls in a way that tacitly assumes they're the same, you should use a named constant
- For functions that have several configuration options, consider defining a single struct to hold all the options, and pass an instance of that
- Replace large or complex nested expressions with named variables
- When the meaning of a function argument is nonobvious, consider one of the following remedies:
-
- Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect
- TODOs should include the string TODO in all caps
- TODOs must followed by the name, bug ID, jira task or other identifier of the person or issue with the best context about the problem referenced by the TODO
// TODO(Jira task) some 'to do' description.
-