# Embedded Learning Library (ELL) style guide

## Python

We use [PEP 8](https://www.python.org/dev/peps/pep-0008/) with one exception, we extend the 80 char line limit to 120.

## C++

### File names and extensions
Header files use the extension ".h". Definitions of functions that must be in the header should be moved to the end of the header file in a region surrounded by `#pragma region implementation`/`#pragma endregion implementation` blocks. Source code files use the extension ".cpp" if they are compiled into a .lib or .exe.  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, preferably 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)
* "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 math 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, ideally in an alphabetical order. Next include third-party library headers, like LLVM. Finally, include standard libraries.

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

    #pragma once

    #include "OtherClassFromThisProject.h"

    #include <proj1/include/ClassFromProjectProj1.h>
    #include <proj1/include/AnotherClassFromProj1.h>

    #include <proj2/include/ClassFromProj2.h>

    #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 in the implementation region of .h 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 the implementation region of the .h file

    void Next() { _iterator++; _count++; }  // wrong: multi-instruction implementations belong in .cpp or the implementation region of the .h files

### Virtual functions
`virtual` functions declared in derived classes should use the `override` or `final` keywords, not `virtual`. This is because `override` and
`final` imply `virtual`. Removing `virtual` also protects against unknowingly adding another virtual member function instead of overriding a
member function from a base class, especially in the case where a virtual function has been removed from the base class.

### Unused variables
Variables that are declared or defined but never read from will emit an unused variable warning on all compilers. Avoid unused variables as
much as possible. If you cannot remove the unused variable, then mark all such variables with the `UNUSED` macro. If a variable is only used
in code that conditionally compiles for debug builds (such as `assert` expressions), it should be marked as such with the `DEBUG_USED`
macro, instead of the `UNUSED` macro. Both `UNUSED` and `DEBUG_USED` are defined in `Unused.h` in the `utilities` library.

### 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);

### Error Handling

The c "assert" function usually results in immediate termination of the program, so this should only be used in cases where it should never happen unless there is a logic error in our code.  To this end assert documents the existing invariants, preconditions and post conditions in the code.

Bad input parameters from our public API or bad data read from a file should not result in this kind of assert termination because it is hard to debug, and it provides no useful information to the caller.   Instead, throw the appropriate type of exception as defined in ~/libraries/utilities/include/Exception.h.  This includes the notImplemented case, which you can raise using throw utilities::LogicException(utilities::LogicExceptionErrors::notImplemented);
