7.0 KiB
Overview
This document sets out the expected coding style for those who wish to participate in this project. With this standard we will maintain a readable codebase that can be easily cannibalised by new and old developers alike.
To ensure the codebase meets this standard please install the supplied GIT pre-commit hook into your local copy. You're also required to install the Artistic Style tool on your system for this hook to be successful; you must have version 2.05 or greater installed.
cd restbed/
cp tool/git/pre-commit .git/hooks
chmod +x .git/hooks/pre-commit
most importantly: "know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!" -- Guido van Rossum, Barry Warsaw, Nick Coghlan.
Interpretation
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Table of Contents
- Overview
- Interpretation
- Brackets
- Indentation
- Comments
- Properties/Variables
- Classes
- Enumerations
- Structures
- Methods/Functions
- Whitespace
- Pointers/References
- Exceptions
- Namespaces
- Optimisations
### Brackets
- Allman style broken braces, and avoid unbraced one line conditional statements.
if ( condition == true )
{
...
}
else
{
...
}
Indentation
- Do not use tabs. All indentation is of 4 spaces.
- Class, Namespace, Struct, If, For, Switch, etc.. statements must be indented.
namespace transport
{
class Car( void )
{
public:
Car( const int number_of_wheels ) : m_number_of_wheels
{
switch( m_number_of_wheels )
{
case 1:
break;
default:
break;
}
}
private:
uint8_t m_number_of_wheels;
}
}
Comments
- Comments should be avoided as they add an additional layer of management and/or technical-debt.
- Commenting is just as ineffective as poorly readable code.
- Code should be self documenting with descriptive naming conventions applied to functions, variables, files, directories, etc...
- Commenting may be a sign you need to split the logic into multiple manageable blocks.
Properties/Variables
- Property and Variables names must follow the Snake-case naming convention.
- Property and Variables must be initialised to a known state on declaration.
int limit = 0;
int person_age = 21;
string name = String::empty;
Classes
- Class property names must be prefixed with
m_
and follow the Snake-case naming convention. - Class properties must be initialised to a known state on instance creation.
- Class properties must be private in scope.
- Class getter/setter accessor methods must not return non-const pointers/references.
- There must be no using namespace declarations in class header files.
- Forward declarations are favoured over
#include
within class header files; with the exception of the standard template library. - Empty method bodies (when unavoidable) shall be marked with a single return.
- Public classes must implement an opaque pointer.
- Class names must start each word boundary with an UPPERCASED letter.
class Person
{
public:
Person( void ) : m_age( 0 )
{
return;
}
int get_age( void ) const
{
return m_age;
}
void set_age( const int value )
{
m_age = value;
}
private:
int m_age;.
}
Enumerations
- Enumerations must be strongly typed.
- Enumeration fields must be UPPERCASED.
- Enumeration fields must be initialised to a known state.
- Enumeration names must start each word boundary with an UPPERCASED letter.
enum LogLevel : int
{
INFO = 0000,
DEBUG = 1000,
FATAL = 2000,
ERROR = 3000,
WARNING = 4000,
SECURITY = 5000
}
Structures
- Structure property names must follow the Snake-case naming convention.
- Structure properties must be initialised to a known state on instance creation.
- Structure names must start each word boundary with an UPPERCASED letter.
struct HttpRequest
{
Bytes body = { };
uint16_t port = 80;
double version = 1.1;
std::string host = "";
std::string path = "/";
std::string method = "GET";
std::multimap< std::string, std::string > headers { };
}
Methods/Functions
- Functions and Methods must use the Snake-case naming convention.
- Functions and Methods should perform one mental operation which is reflected in their name.
- Function and Method declarations should avoid similar argument types.
- It is recommended that Functions and Methods are no greater than 70 lines of code. If you find that the LOC exceed this limit, it may be an indication that it is performing more than one mental operation; see rule 2.
int ping( Hostname hostname, Interface interface, int16_t port )
{
auto port = port;
auto hostname = hostname.to_string( );
auto interface = hostname.to_string( )
...
return ttl;
}
Whitespace
- Whitespace is free, don't be scared to use it.
int process_exit_status = 0;
const string filename = "/bin/ls";
do
{
Process reaction = load_process( filename );
reaction.run( );
process_exit_status = reaction.get_exit_status( );
}
while ( process_exit_status not_eq -1 );
Pointers/References
- Pointers and References must be aligned to the data type (left).
int* age = nullptr;
char* forename = nullptr;
string& surname = m_surname;
Exceptions
- Logic within catch-blocks must be short & sweet.
- Name exceptions per Java styling.
try
{
start( );
}
catch ( const invalid_argument& ia )
{
stop( );
}
catch ( const runtime_error& re )
{
stop( );
}
catch ( const exception& ex )
{
stop( );
}
Namespaces
- Do not include entire Namespaces, import only the artifact you're interested in.
- Namespace names must only contain lowercased letters.
using std::mutex;
using std::string;
using std::thread;
namespace restbed
{
...
}
Optimisations
- Avoid premature optimisation, readable, maintainable code is more important.