Difference between revisions of "RidgeRun Developer Manual/Coding Styles/C++"

From RidgeRun Developer Connection
Jump to: navigation, search
(Good practices)
m
 
(20 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
<noinclude>
 
<noinclude>
{{RidgeRun Developer Manual/Head|previous=Coding Styles/C|next=Coding Styles/Python|keywords=}}
+
{{RidgeRun Developer Manual/Head|previous=Coding Styles/C|next=Coding Styles/Python|metakeywords=}}
 
</noinclude>
 
</noinclude>
  
Line 6: Line 6:
  
 
When writing software source code there are many coding styles as the concept covers a lot of aspects (some of them subjective). In general RidgeRun tries to follow the [https://google.github.io/styleguide/cppguide.html Google C++ Style Guide].
 
When writing software source code there are many coding styles as the concept covers a lot of aspects (some of them subjective). In general RidgeRun tries to follow the [https://google.github.io/styleguide/cppguide.html Google C++ Style Guide].
 +
 +
Here we summarize some of the most common concepts, in case of doubt and for more information, please refer to [https://google.github.io/styleguide/cppguide.html Google C++ Style Guide].
  
 
== Good practices ==
 
== Good practices ==
Line 12: Line 14:
  
 
In general, if you are adding code to an existent code, be consistent with the coding standard already being used. If no standard is used then follow this guide.
 
In general, if you are adding code to an existent code, be consistent with the coding standard already being used. If no standard is used then follow this guide.
 +
 +
=== Self contained headers ===
 +
 +
Header files should be self-contained (compile on their own) and end in .h. Non-header files that are meant for inclusion should end in .inc and be used sparingly.
 +
 +
All header files should be self-contained. Users and refactoring tools should not have to adhere to special conditions to include the header. Specifically, a header should have header guards and include all other headers it needs.
 +
 +
Read more [https://google.github.io/styleguide/cppguide.html#Self_contained_Headers here]
 +
 +
=== The #define Guard ===
 +
 +
All header files should have '''#define''' guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.
 +
 +
For example, the file foo/src/bar/baz.h in project foo should have the following guard:
 +
 +
<syntaxhighlight lang="c++">
 +
#ifndef FOO_BAR_BAZ_H_
 +
#define FOO_BAR_BAZ_H_
 +
 +
...
 +
 +
#endif  // FOO_BAR_BAZ_H_
 +
</syntaxhighlight>
 +
 +
=== Include what you use ===
 +
 +
If a source or header file refers to a symbol defined elsewhere, the file should directly include a header file which properly intends to provide a declaration or definition of that symbol. It should not include header files for any other reason.
 +
 +
=== Local variables ===
 +
 +
Place a function's variables in the narrowest scope possible, and initialize variables in the declaration. C++ allows you to declare variables anywhere in a function. We encourage you to declare them in as local a scope as possible, and as close to the first use as possible.
 +
 +
Se [https://google.github.io/styleguide/cppguide.html#Local_Variables here] for examples.
  
 
=== Comments ===
 
=== Comments ===
Line 31: Line 66:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== Inclusive language ===
 +
 +
In all code, including naming and comments, use inclusive language and avoid terms that other programmers might find disrespectful or offensive (such as "master" and "slave", "blacklist" and "whitelist", or "redline"), even if the terms also have an ostensibly neutral meaning. Similarly, use gender-neutral language unless you're referring to a specific person (and using their pronouns). For example, use "they"/"them"/"their" for people of unspecified gender (even when singular), and "it"/"its" for software, computers, and other things that aren't people ([https://google.github.io/styleguide/cppguide.html#Inclusive_Language reference]).
  
 
=== Use a license and authors header ===
 
=== Use a license and authors header ===
Line 52: Line 91:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Conditionals ===
+
=== Consistent indentation ===
 +
 
 +
* Use only spaces and indent 2 paces at a time. Don't use tabs.
 +
 
 +
=== Avoid unnecessary separators ===
 +
 
 +
One single empty line is fine to separate logical blocks. Avoid multiple empty lines, commented empty lines, etc.
 +
 
 +
== Naming ==
 +
 
 +
=== File names ===
 +
 
 +
Filenames should be all lowercase and can include underscores (_) or dashes (-). Follow the convention that your project uses. If there is no consistent local pattern to follow, prefer "_".
 +
 
 +
<syntaxhighlight lang="c++">
 +
my_useful_class.cc
 +
my-useful-class.cc
 +
</syntaxhighlight>
 +
 
 +
=== Type names ===
 +
 
 +
Type names use MixedCase (start with a capital letter and have a capital letter for each new word, with no underscores). The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention.
 +
 
 +
 
 +
<syntaxhighlight lang="c++">
 +
 
 +
 
 +
// classes and structs
 +
class UrlTable { ...
 +
class UrlTableTester { ...
 +
struct UrlTableProperties { ...
 +
 
 +
// typedefs
 +
typedef hash_map<UrlTableProperties *, std::string> PropertiesMap;
 +
 
 +
// using aliases
 +
using PropertiesMap = hash_map<UrlTableProperties *, std::string>;
 +
 
 +
// enums
 +
enum class UrlTableError { ...
 +
</syntaxhighlight>
 +
 +
=== Variable naming ===
 +
 
 +
All variables names should follow the same standard. If the code is an extension of an existing framework/library, it should follow the existing standard. For example:
 +
 
 +
<syntaxhighlight lang="c">
 +
int mixedCamelCaseVariable;
 +
int CamelCaseVariable;
 +
int snake_case_variable;
 +
int horribleStandard_Variable;
 +
</syntaxhighlight>
 +
 
 +
All new projects should use '''snake_case''' (all lower case with underscores between words).
 +
 
 +
The names of variables (including function parameters) and data members are all lowercase, with underscores between words. Data members of classes (but not structs) additionally have trailing underscores. For instance: '''a_local_variable''', '''a_struct_data_member''', '''a_class_data_member_'''.
 +
 
 +
=== Constant names ===
 +
 
 +
Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by '''MixedCase'''.
 +
 
 +
<syntaxhighlight lang="c">
 +
const int kMyConstant = 5;
 +
</syntaxhighlight>
 +
 
 +
=== Struct data members ===
 +
 
 +
Struct data members are named like regular variables ('''snake_case''' (all lower case with underscores between words)).
 +
 
 +
<syntaxhighlight lang="c">
 +
struct UrlTableProperties {
 +
  std::string name;
 +
  int num_entries;
 +
  static Pool<UrlTableProperties>* pool;
 +
};
 +
</syntaxhighlight>
 +
 
 +
=== Class Data Members ===
 +
 
 +
Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore. See [https://google.github.io/styleguide/cppguide.html#General_Naming_Rules here] for more information.
 +
 
 +
<syntaxhighlight lang="c">
 +
class MyClass {
 +
  ...
 +
private:
 +
  int var_name_;  /* OK - underscore at end */
 +
  static int static_var_;  /* OK */
 +
};
 +
</syntaxhighlight>
 +
 
 +
=== Namespaces ===
 +
 
 +
Namespace names are '''snake_case''' (all lower-case, with words separated by underscores). Top-level namespace names are based on the project name. See [https://google.github.io/styleguide/cppguide.html#Namespace_Names here] for more information.
 +
 
 +
=== Method/function naming standard ===
 +
 
 +
All method names should follow the same standard. If the code is an extension of an existing framework/library, it should follow the existing standard. For example:
 +
 
 +
<syntaxhighlight lang="c">
 +
void mixedCamelCaseFunction ();
 +
void CamelCaseFunction ();
 +
void snake_case_function ();
 +
void horribleStandard_Function ();
 +
</syntaxhighlight>
 +
 
 +
All new projects should follow [https://google.github.io/styleguide/cppguide.html#Function_Names this standard]:
 +
 
 +
Function names should use '''MixedCase'''. Start with a capital letter and have a capital letter for each new word.
 +
 
 +
<syntaxhighlight lang="c">
 +
/*Regular function*/
 +
FunctionName();
 +
</syntaxhighlight>
 +
 
 +
=== Enumerators ===
 +
 
 +
Enumerators (for both scoped and unscoped enums) should be named like constants, not like macros. That is, use kEnumName not ENUM_NAME.
 +
 
 +
<syntaxhighlight lang="c">
 +
enmu class MyEnum {
 +
kFieldOne,
 +
kFieldTwo,
 +
};
 +
</syntaxhighlight>
 +
 
 +
=== Macros ===
 +
 
 +
Macros are all uppercase and words separated by undersclore.
 +
 
 +
<syntaxhighlight lang="c">
 +
#define MY_MACRO  5
 +
</syntaxhighlight>
 +
 
 +
== Conditionals ==
  
 
*Keep the constants at the left side of a comparisons. This applies to all [https://en.cppreference.com/w/cpp/language/operator_comparison C++ comparison operators]. For example:
 
*Keep the constants at the left side of a comparisons. This applies to all [https://en.cppreference.com/w/cpp/language/operator_comparison C++ comparison operators]. For example:
Line 80: Line 252:
  
  
For header ordering we use an inside-out approach, this is, the local header goes first and the system headers go last so the header inclusion shoul go as follows:
+
For header ordering we use an inside-out approach, this is, the local header goes first and the system headers go last so the header inclusion should go as follows:
  
  

Latest revision as of 05:25, 9 March 2023




Previous: Coding Styles/C Index Next: Coding Styles/Python




Introduction to 'C++' Coding Styles

When writing software source code there are many coding styles as the concept covers a lot of aspects (some of them subjective). In general RidgeRun tries to follow the Google C++ Style Guide.

Here we summarize some of the most common concepts, in case of doubt and for more information, please refer to Google C++ Style Guide.

Good practices

Be consistent with current code

In general, if you are adding code to an existent code, be consistent with the coding standard already being used. If no standard is used then follow this guide.

Self contained headers

Header files should be self-contained (compile on their own) and end in .h. Non-header files that are meant for inclusion should end in .inc and be used sparingly.

All header files should be self-contained. Users and refactoring tools should not have to adhere to special conditions to include the header. Specifically, a header should have header guards and include all other headers it needs.

Read more here

The #define Guard

All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.

For example, the file foo/src/bar/baz.h in project foo should have the following guard:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

...

#endif  // FOO_BAR_BAZ_H_

Include what you use

If a source or header file refers to a symbol defined elsewhere, the file should directly include a header file which properly intends to provide a declaration or definition of that symbol. It should not include header files for any other reason.

Local variables

Place a function's variables in the narrowest scope possible, and initialize variables in the declaration. C++ allows you to declare variables anywhere in a function. We encourage you to declare them in as local a scope as possible, and as close to the first use as possible.

Se here for examples.

Comments

  • Always use /*ANSI-C style comments*/
  • Avoid inline comments:

Yes:

/*This is a comment*/
if ( nullptr == var ) {
  /*...*/
}

No:

if ( nullptr == var ) { /*This is a comment*/
  /*...*/
}

Inclusive language

In all code, including naming and comments, use inclusive language and avoid terms that other programmers might find disrespectful or offensive (such as "master" and "slave", "blacklist" and "whitelist", or "redline"), even if the terms also have an ostensibly neutral meaning. Similarly, use gender-neutral language unless you're referring to a specific person (and using their pronouns). For example, use "they"/"them"/"their" for people of unspecified gender (even when singular), and "it"/"its" for software, computers, and other things that aren't people (reference).

Use a license and authors header

All software need some sort of license and authors documentation, for instance:

/*
 *  Copyright (C) 2020 RidgeRun, LLC (http://www.ridgerun.com)
 *  All Rights Reserved.
 *  Authors: Name Lastname <myemail@something.com>
 *           Name Lastmane <otheremail@something.com>
 *
 *  The contents of this software are proprietary and confidential to RidgeRun,
 *  LLC.  No part of this program may be photocopied, reproduced or translated
 *  into another programming language without prior written consent of
 *  RidgeRun, LLC.  The user is free to modify the source code after obtaining
 *  a software license from RidgeRun.  All source code changes must be provided
 *  back to RidgeRun without any encumbrance.
 */

Consistent indentation

  • Use only spaces and indent 2 paces at a time. Don't use tabs.

Avoid unnecessary separators

One single empty line is fine to separate logical blocks. Avoid multiple empty lines, commented empty lines, etc.

Naming

File names

Filenames should be all lowercase and can include underscores (_) or dashes (-). Follow the convention that your project uses. If there is no consistent local pattern to follow, prefer "_".

my_useful_class.cc
my-useful-class.cc

Type names

Type names use MixedCase (start with a capital letter and have a capital letter for each new word, with no underscores). The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention.


// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// typedefs
typedef hash_map<UrlTableProperties *, std::string> PropertiesMap;

// using aliases
using PropertiesMap = hash_map<UrlTableProperties *, std::string>;

// enums
enum class UrlTableError { ...

Variable naming

All variables names should follow the same standard. If the code is an extension of an existing framework/library, it should follow the existing standard. For example:

int mixedCamelCaseVariable;
int CamelCaseVariable;
int snake_case_variable;
int horribleStandard_Variable;

All new projects should use snake_case (all lower case with underscores between words).

The names of variables (including function parameters) and data members are all lowercase, with underscores between words. Data members of classes (but not structs) additionally have trailing underscores. For instance: a_local_variable, a_struct_data_member, a_class_data_member_.

Constant names

Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by MixedCase.

const int kMyConstant = 5;

Struct data members

Struct data members are named like regular variables (snake_case (all lower case with underscores between words)).

struct UrlTableProperties {
  std::string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
};

Class Data Members

Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore. See here for more information.

class MyClass {
  ...
 private:
  int var_name_;  /* OK - underscore at end */
  static int static_var_;  /* OK */
};

Namespaces

Namespace names are snake_case (all lower-case, with words separated by underscores). Top-level namespace names are based on the project name. See here for more information.

Method/function naming standard

All method names should follow the same standard. If the code is an extension of an existing framework/library, it should follow the existing standard. For example:

void mixedCamelCaseFunction ();
void CamelCaseFunction ();
void snake_case_function ();
void horribleStandard_Function ();

All new projects should follow this standard:

Function names should use MixedCase. Start with a capital letter and have a capital letter for each new word.

/*Regular function*/
FunctionName();

Enumerators

Enumerators (for both scoped and unscoped enums) should be named like constants, not like macros. That is, use kEnumName not ENUM_NAME.

enmu class MyEnum {
 kFieldOne,
 kFieldTwo,
};

Macros

Macros are all uppercase and words separated by undersclore.

#define MY_MACRO  5

Conditionals

if ( nullptr == var ) {
  // ...
}

This is to avoid possible bugs like:

if ( var = nullptr ) {
  // ...
}

A derived good practice is to use const keyword as much as you can:

const int val = 1;

if (val = 2) { // This should not compile
    ...
}

Header ordering

For header ordering we use an inside-out approach, this is, the local header goes first and the system headers go last so the header inclusion should go as follows:


1. Header file defining the functions implemented in the source file.

2. Other headers from the same project

3. Headers from non-standard projects

4. System headers (with angle brackets and .h extension)

5. C++ standard headers (with angle brackets without an extension)


A blank line should be added between each block of headers and the headers should go in alphabetical order in each block.

In an ideal world, header files should be self-contained and the include order shouldn't matter, however, this is not always the case, and if the order matters is a sign something is wrong in your code. Having the header file declaring the functions in the source file as the first include helps make sure my header is in fact self-contained. If it shows any error is a sign something is wrong.

Also, if an out-of-order include is needed it is a sign that something is not right in either your code or the external headers. If the problem is in your code, the best thing to do is to fix it but if not, the reason for the out-of-order include should be very well documented.

Here is an example of how the includes should look.

#include "my_module.h"

#include "other_header.h"

#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>


Previous: Coding Styles/C Index Next: Coding Styles/Python