Skip to content
This repository has been archived by the owner on May 14, 2020. It is now read-only.

Coding Standards

Luis edited this page May 9, 2014 · 24 revisions

Root namespace: trillek

Indentation

  • Indentation: 4 spaces
  • Avoid exceeding a line length of more than 80 characters.
  • Lines longer than 120 characters are forbidden.
  • Bracket Location:
    if (x < 0) {
        puts("Negative");
        negative(x);
    }
    else {
        puts("Non-negative");
        nonnegative(x);
    }
  • Switch:
switch (suffix) {
case 'G':
case 'g':
{
    // new scope
}
    break;
case 'M':
default:
    break;
}
  • Namespaces :
namespace trillek {
namespace galaxy {
namespace jupiter {

static const int IM_IMPORTANT = 32;

class Foo {
public:
    int x;
    ...
private:
    int i;
    ...
};
...

} // End of namespace jupiter
} // End of namespace galaxy
} // End of namespace trillek

Naming

Give as descriptive a name as possible, within reason. Do not worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader. Do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word.

int price_count_reader;    // No abbreviation.
int num_errors;            // "num" is a widespread convention.
int num_dns_connections;   // Most people know what "DNS" stands for.
int i,j,k,n,x,y,z;         // Typical loop counter variables. Try to no abuse of it 

int nerr;                  // Ambiguous abbreviation.
int n_comp_conns;          // Ambiguous abbreviation.
int wgc_connections;       // Only your group knows what this stands for.
int pc_reader;             // Lots of things can be abbreviated "pc".
int cstmr_id;              // Deletes internal letters.

NOTE: These points are still in discussion and subject to change

  • Files: lowercase with underscores (_) or dashes (-)
  • Classes/Structs/Enums/Typedefs: UpperCamelCase. Example :
class UrlTableTester { ...
struct UrlTableProperties { ...

// typedefs
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
typedef uint8_t  Byte;

// enums
enum UrlTableErrors {
  • Variables: lowercase and _ :
string table_name;  // OK - uses underscore.
string tablename;   // OK - all lowercase.
  • Functions/Class methods: UpperCamelCase and _ to separate phrases. Example :
void PurgueCacheLines();

class Foo {
public:
    int GetTotalFoos();
};
  • Constants and Enum entries: all capitals and _ . Example:
const float PI = 3.1416....;
enum class Colors {
    RED, 
    BLUE, 
    GREEN
};
constexpr float DESTRUCTION_RATIO = 0.1f;

Comments

We are going to use Doxygen, so we follow that style of comments. The most important is a short descriptive text of the class/struct/attribute. Entries for parameters or a detailed description are recommended, especially when doing something complex.

  • Functions & methods :
/**
 * \brief Returns a resource with the specified name.
 *
 * Bla bla bla bla bla bla bla ... (Optional detailed description)
 * \param[in] const std::vector<Property> &properties The creation properties for the resource.
 * \return bool True if initialization finished with no errors.
 */

or

/** \brief Remove and get a reference of an element
 * 
 * Bla bla bla bla bla bla bla ... (Optional detailed description)
 * \param key const K& the key of the element
 * \param element T& a non-const reference that will contain the element
 * \return bool true if removed, false otherwise
 */

or

/// \brief Remove and get a reference of an element
/**
 * Bla bla bla bla bla bla bla ... (Optional detailed description)
 * \param key const K& the key of the element
 * \param element T& a non-const reference that will contain the element
 * \return bool true if removed, false otherwise
 */
  • For class attributes, constants, static vars, and global variables (ouch!) :
static const double PI = 3.14159265358979324; /// PI constant

static const double TAU = 2 * PI;  /// 2*PI constant

static bool UberFlag;     /// Uber important flag
                           /// (Optional detailed description) Indicates when we need to change the 
                           /// polarity of the neutron beam in the dilithium chamber.

Pointers

Whenever you need pointers, use std::unique_ptr in most cases, std::shared_ptr only when necessary and raw pointers only when it is required.

When you initialize a class or declare a pointer, set it to nullptr. Also, when you free a pointer, first check if it is 1= of nullptr and then free it, later set it to nullptr. This allow to keep better control of memory managed by new/delete & malloc/free, as we can assume that if the pointer is nullptr then was free or never was initialized.

Variables and Constants

Avoid the usage of global variables. Also try to avoid the usage of preprocessor constants, instead use static const variables for constants as they have both type and scope, making them safer to use.

When you define a pointer or a reference, try to keep the * or & or && next to the type and not the name.

Header files

We use the .hpp extension and use #ifndef guards to protect headers. Also, we recommend putting a header comment block like this, just after the guards and before any #include:

/**
* \brief Module that handles the neutrons in the dilithium chamber
* \file Neutrons.hpp
* \copyright License
*
*/

Source files

All source uses the .cpp extension.

Included files

For included files that contains constants/data tables (Carmack's trick), we recommend using extension .inc and add a comment explaining the contents of the included file.

Specialized template member functions

Templatizing a member function is common, but specializing it for fixed parameter values and using the specialized functions requires some tricks. Here is an example using a templated function MyClass::MyFunction():

  • Put the template declaration and optional default implementation in the class in the header file MyClass.hpp:
class MyClass {
    template<class T> void Myfunction();
}
  • Put the specialized functions in MyClassTemplates.cpp:
#include "MyClass.hpp"
template<> void MyClass::MyFunction<MyType1>() {...}
template<> void MyClass::MyFunction<MyType2>() {...}
  • Put the extern declaration in MyClassTemplates.hpp:
#include "MyClass.hpp"
extern template void MyClass::MyFunction<MyType1>();
extern template void MyClass::MyFunction<MyType2>();
  • Include MyClassTemplates.hpp wherever the specialized functions are used, but do not include it in MyClassTemplates.cpp as you would normally do.