266 lines
7.0 KiB
Markdown
266 lines
7.0 KiB
Markdown
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](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) hook into your local copy. You're also required to install the [Artistic Style](http://astyle.sourceforge.net/) 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](http://tools.ietf.org/pdf/rfc2119.pdf).
|
||
|
||
Table of Contents
|
||
-----------------
|
||
|
||
1. [Overview](#overview)
|
||
2. [Interpretation](#interpretation)
|
||
3. [Brackets](#brackets)
|
||
4. [Indentation](#indentation)
|
||
5. [Comments](#comments)
|
||
6. [Properties/Variables](#propertiesvariables)
|
||
7. [Classes](#classes)
|
||
8. [Enumerations](#enumerations)
|
||
9. [Structures](#structures)
|
||
10. [Methods/Functions](#methodsfunctions)
|
||
11. [Whitespace](#whitespace)
|
||
12. [Pointers/References](#pointersreferences)
|
||
13. [Exceptions](#exceptions)
|
||
14. [Namespaces](#namespaces)
|
||
15. [Optimisations](#optimisations)
|
||
|
||
### Brackets
|
||
|
||
- Allman style broken braces, and avoid unbraced one line conditional statements.
|
||
|
||
```C++
|
||
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.
|
||
|
||
```C++
|
||
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](https://en.wikipedia.org/wiki/snake_case).
|
||
- Property and Variables **must** be initialised to a known state on declaration.
|
||
|
||
```C++
|
||
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](https://en.wikipedia.org/wiki/snake_case).
|
||
- 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](http://en.wikipedia.org/wiki/Opaque_pointer).
|
||
- Class names **must** start each word boundary with an UPPERCASED letter.
|
||
|
||
```C++
|
||
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.
|
||
|
||
```C++
|
||
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](https://en.wikipedia.org/wiki/snake_case).
|
||
- Structure properties **must** be initialised to a known state on instance creation.
|
||
- Structure names **must** start each word boundary with an UPPERCASED letter.
|
||
|
||
```C++
|
||
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](https://en.wikipedia.org/wiki/snake_case).
|
||
- 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](https://en.wikipedia.org/wiki/Source_lines_of_code) exceed this limit, it may be an indication that it is performing more than one mental operation; see rule 2.
|
||
|
||
```C++
|
||
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.
|
||
|
||
```C++
|
||
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).
|
||
|
||
```C++
|
||
int* age = nullptr;
|
||
char* forename = nullptr;
|
||
string& surname = m_surname;
|
||
```
|
||
|
||
### Exceptions
|
||
|
||
- Logic within catch-blocks **must** be short & sweet.
|
||
- Name exceptions per Java styling.
|
||
|
||
```C++
|
||
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.
|
||
|
||
```C++
|
||
using std::mutex;
|
||
using std::string;
|
||
using std::thread;
|
||
|
||
namespace restbed
|
||
{
|
||
...
|
||
}
|
||
```
|
||
|
||
### Optimisations
|
||
|
||
- Avoid premature optimisation, **readable, maintainable code is more important**.
|