Skip to content

Coding and Style Guide

Romain Lacroix edited this page Nov 30, 2022 · 2 revisions

This document describes the coding guidelines which must be used when contributing to any of the NFs of the OAI CN. Some of them are enforced by the pipeline (such as formatting) and some are checked by the reviewers and maintainers. Don't worry if you do not follow them for your first MRs, we will help you adapt your code.

Coding style

Each NF has a .clang-format file in the src folder. This file contains the format definitions. Ensure that you run:

clang-format-9 -i <changed_file> 

before committing.

You can also use git pre-hooks or integrate clang-format-9 into your preferred IDE.

Coding Guidelines

We recommend that you use a static code analyzer ("linter") to check your code. We recommend clang-tidy. It covers most rules described below.

It is enabled by default in the CLion IDE and can be enabled in VS Code.

Do not repeat yourself (DRY)

Don't copy and paste code which only slightly differs. This is a common source for errors and it makes the code base complicated and unnecessarily large.

Instead, split your code into several functions, which are general enough that they can handle different cases (e.g. using parameters). Also ensure that your functions are not too general. They should cover exactly one well-defined functionality and should be small in size.

We recommend that you do that even if there is no other caller for now, as the code may be enhanced.

Use of virtual

Every public or protected function in a base class shall be marked with the virtual decorator.

Use of override

Every overriding function in a sub-class shall be marked with the override decorator. When a virtual function is overridden, use the override decorator instead of virtual.

Destructor decoration

Destructors shall be marked in the same style as above: Use virtual for base classes and override for sub-classes.

Use of nodiscard

When you define a function where the return value must not be ignored, mark this function with [[nodiscard]].

This especially applies to:

  • Getters
  • Functions that return a status code indicating success or failure

Be careful that you do not use [[nodiscard]] per default. As a rule of thumb, only apply it to the two use cases mentioned above.

Use smart pointers

We never use raw pointers for dynamic memory management. We also never use new, delete, malloc or free (or other C-style memory management functions).

Instead, we always use smart pointers from <memory>.

We initialize the smart pointers using the functions std::make_shared or std::make_unique, we do not use the new keyword in combination with smart pointers.

Const-correctness, avoiding unnecessary copies

Do use constant references wherever possible. For parameters, instead of writing: void function(TypeA obj) use: void function(const TypeA& obj).

Also, when you return an object, use constant references, e.g. for a getter: const TypeA& getA() const, except when the returned value is a temporary.

Exception to the use of const-references: for primitive types (int, float, char, raw pointers, ...), do not use const-references but pass parameters or return by value, as these types are the same size (or less) as references.

When the function does not change the state of an object, declare the function itself as const (see the getter above).

Use of Exceptions

Usage of exceptions is preferred to the "C-style" return value based programming. (To be discussed with Team)

  1. Home
  2. Configuration for Network Functions

Clone this wiki locally