Skip to content

Latest commit

 

History

History
136 lines (92 loc) · 6.32 KB

StyleGuide.md

File metadata and controls

136 lines (92 loc) · 6.32 KB

Embedded Learning Library (ELL) style guide

This is the C++ coding style guide for the ELL project.

File names and extensions

Header files use the extension ".h". Source code files use the extension ".cpp" if they are compiled into a .lib or .exe, and ".tcc" if they contain templated source code. Each file should typically contain a single class and its name should match the class name.

Projects

A project is a set of source files that compile into a single executable or library, or that implement a single template library.

Project naming:

Projects have camelCase names, preferrably single word, such as "model", "utilities", "compile".

Directory, namespace, output naming:

All of the source code in a project should be defined in a namespace that shares the project name. All of the source files associated with a project should be contained in a directory that shares the project name. The executable or library generated by a project should share the project name.

Project directory structure:

Each project is contained in a directory. The directory contains a CMakeLists.txt file. The directory typically contains the following subdirectories:

  • "include", for h files
  • "src" for cpp files (unless the project defines a template library without cpp files)
  • "tcc" for tcc files (these define implementaitons of template classes)
  • "test" for source files that define unit tests, invoked via ctest
  • "doc" for documentation that does not fit in the source files themselves. For example, complex mathy algorithms may require detailed documentation in a latex file, which would live in the doc directory

Additionally, the directory can contain a README.md file.

Naming

Names should be descriptive and self-evident, rather than terse. Use whole words rather than abbreviations. Example: use GetFunctionDefinition instead of GetFuncDef. Exceptions to this rule are:

  • Use "Num" as abbreviation for "Number"
  • Use Size for a member function that returns the size of an object (instead of GetSize)

Classes, structs, enum classes: use PascalCase, e.g., class MyClass {};

use camelCase for name of enum values e.g., enum MyEnum { valueOne, valueTwo };

Functions, member and non-member:
use PascalCase, e.g., int GetValue() const { return _value; }

When possible, function names should be imperative mood verbs, e.g., GetValue() and Permute(). Specifically, accessor member functions should start with Get, e.g., GetOutputVector(). Exceptions to this rule are:

  • member functions that returns the size of an object, which can simply be Size()
  • type conversion functions, which can start with To, e.g., ToString()
  • functions that return the number of elements in a collection, which can start with Num, e.g. NumVariables()

Method and Function arguments: camelCase: e.g., int GetValue(int rowIndex, int columnIndex);

Member variables: Use _ (underscore) followed by camelCase, e.g., _myMemberVariable

Template typenames: Use PascalCase and add the suffix "Type", e.g., template <typename SparseVectorType>

Template variables that are not typenames: Use camelCase, e.g., template <size_t size>

File structure

All source code files should start with a header that specifies project name, file name, and author list (see example below)

.h files should indicate #pragma once immediately after the header

Next, indicate all #include statements. First, include files from the local project. Second, include files from other projects, grouping by project and adding the project name as a comment. Finally, include standard libraries.

//////////////////////////////////////////////////////////////////////////////////////////////////// 
// 
//  Project:  Embedded Learning Library (ELL)
//  File:     FileName.h (libraryName)
//  Authors:  Author1, Author2
//
//////////////////////////////////////////////////////////////////////////////////////////////////// 

#pragma once

#include "OtherClassFromThisProject.h"

// proj1
#include "ClassFromProjectProj1.h"
#include "AnotherClassFromProj1.h"

// proj2
#include "ClassFromProj2.h"

// stl
#include <vector>
#include <string>

In certain cases, normal #ifndef-style include guards are required instead of using #pragma once. In this case, add the guard name in a comment after the #endif:

#ifndef MATRIX_H
#define MATRIX_H

...

#endif // MATRIX_H

Function implementations

Almost all function implementations belong in .cpp and .tcc files. The exception is short single-instruction implementations of parameterless functions, which should appear in the .h file on the same line as the function declaration. For example:

double GetValue() const { return _value; }  // inline implementation in .h file

double SetValue(double value);  // function has parameters - implementation belongs in .cpp or .tcc file

void Next() { _iterator++; _count++; }  // wrong: multi-instruction implementations belong in .cpp or .tcc files

int GetIndex()  // wrong: inline implementation should occupy a single line
{
    return _index;
}

Formatting

Use clang-format to enforce correct formatting. Use the definitions in the file .clang-format, which is found in the main project directory.

Documentation

All public classes, functions, and variables that are declared in .h files should be preceded by an XML documentation block. The only exception is functions that are defined with =default or =delete, which should not be documented. Each documentation row should begin with three slashes (///) and the first line in a documentation block should contain a summary tag. Follow this example:

/// <summary> Mathematical power operation. </summary>
///
/// <param name="base"> The base number. </param>
/// <param name="exponent"> The exponent number. </param>
///
/// <returns> Base number to the power of the exponent number. </returns>
double Power(double base, double exponent);

/// <summary> Performs an in-place sort. </summary>
///
/// <typeparam name="RandomAccessContainerType"> The container type, which must implement a square bracket operator. </typeparam>
/// <param name="container"> [in,out] The container being sorted. </param>
template<typename RandomAccessContainerType>
void InplaceSort(RandomAccessContainerType& container);