Coding Guidelines
General
openPASS (Open Source) is based on modern C++ (currently C++17). For coding guidelines, please refer to ISO C++ Core Guidelines.
Headers/Sources
Use
*.h
as file extension for header filesUse
*.cpp
as file extension for source files
Naming Conventions
Concise summarized Naming Conventions
#pragma once
namespace openpass::component::algorithm
{
/* fooBar.h */ // File: lowerCamelCase
class FooBar // Class: UpperCamelCase
{
private:
static constexpr int MAGIC_NUMBER {-999}; // Constants: UPPER_CASE
int myMember; // Members: lowerCamelCase
FooBar(); // Ctor: UpperCamelCase
public:
void Bar(); // Methods: UpperCamelCase
void BarBar(bool flag, int counter); // Arguments: lowerCamelCase
void YaaBar(); /// Yaa = Yet Another Abbreviation // Abbreviations: UpperCamelCase
};
}
Namespaces
Use lowercase for namespaces
Use singular form for namespaces where appropriate
Use base namespace
openpass
Core uses
openpass::core::*
Components use
openpass::component::*
Use the appropriate namespace for the type your component *
openpass::component::algorithm
*openpass::component::sensor
*openpass::component::dynamics
*openpass::component::driver
* …Code with shared scope (e.g.
common
) namespaces are separated in
For everyone
openpass::common
e.g.openpass::common::XmlParser
Common for components
openpass::component::common
e.g.openpass::components::Ports
For the core only
openpass::core::common
e.g.openpass::core::common::Parameters
Discussion:
openpass::type::*
Example:
openpass::type::Vector2D, openpass::type::OpenDriveId
Interfaces
Interfaces should be named descriptively according to the functionality they outline with an
UpperCamelCase
nameExample: Interface for the world =
class WorldInterface
Interfaces are abstract classes, and as such provide pure virtual functions only, withtout any default implementation. For example:
virtual double GetDistance() const = 0;
Interface methods do not exibit default parameters.
We excessively use gmock, so for every interface a fake interface should be provided
Example:
class FakeWorld : public WorldInterface {...};
Note: Following *Roy Osherove*, we use Fake instead of Mock, whick allows to distinguish Mocks and Stubs more easily in the code
Classes
Classes should be named descriptively according to the functionality they implement with an
UpperCamelCase
nameA Class implementing an Interface should have the Interfaces name (see below), with the Interface portion removed. For example: .. code-block:
class AgentBlueprint : public AgentBlueprintInterface {...};
Methods
Methods should be descriptively named in
UpperCamelCase
Example: Method for retrieving the time of day should be named
GetTimeOfDay()
Member Variables
Member variables should be descriptively named in
lowerCamelCase
Normally, it is sufficient to use the classes name directly.
Example: The member variable containing the AgentNetwork should be named
agentNetwork
Input / Output Signal Naming
Components use a special form of signal transmission. For easier use, the following abstraction is recommended: .. code-block:
std::map<int, ComponentPort *> outputPorts; bool success = outputPorts.at(localLinkId)->SetSignalValue(data);std::map<int, ComponentPort *> inputPorts; bool success = inputPorts.at(localLinkId)->GetSignalValue(data);Discussion: Wrap in
openpass::components::common::Port
and furtheropenpass::components::common::Ports
Additional Information
Use
UpperCamelCase
for abbreviations used in files, classes, methods, or variablesThis does not apply if the abbreviation is the entire name or the beginning of the name - in such a case the name is written with the rules for the appropriate type
int ID→int id
class AgentID→ class AgentId
ADASDriver.cpp→adasDriver.cpp
Avoid public class data members. If unavoidable, use
lowerCamelCase
Enums should be preferably defined as enum class; as such, enum names should be in
UpperCamelCase
Decorate container by type aliases and use UpperCamelCase. For example:
using FooParts = std::vector<FooPart>;
Avoid
Do not use Hungarian notation for variables names (iCounter → counter)
Do not specify the type of the underlying implementation (partMap→ parts)
Do not use magic numbers in the code; explicitly define constants instead
Do not use global variables
Exceptions
Autogenerated code does not need to follow the coding conventions
Example:: Signals/Slots (QT):
void on_button_clicked();
Documentation
The following should be documented * Public functions and class methods * Classes * File headers * Constants * Private functions or methods with more than 3 arguments and/or complex functionality??
Language
Document “what” it does rather than describing “why”
Third-person singular verbs should be used to describe what it does
Use the below methods to comment in source code. The below 2 syntaxes must be placed just above an entity.
Multi line comments
//! … comments… //! … comments… //! … comments…Single line comments
/// Comments.Use the following structural commands
Syntax
Definition
@file
The file name must be present in the file header
@param[in/out]
Parameter documentation for functions
@page
Markdown page name
Use the following syntax for parameter description
@param[in/out] <variable name> <variable description>All parameters description should be aligned as shown below to make them more readable.
@param[in] shortName Description. @param[in] longerName Description. @param[out] veryLongName Description.Example
/// @file main.c #include<stdio.h> /// Mathematical constant PI #define PI 3.1415 /// Radius in meters #define RADIUS_M 7.82 //! Calculates the area of the circle. //! //! @param[in] radius Radius of the circle //! @param[out] area Area of the circle float CalculateArea(float radius) { float area; area = PI * radius * radius; return area; }Do not comment on polymorph methods (virtual base → override), unless there is a severe change
End Of Line
Native end of line (EOL) should be used in the working directory
The
.gitattributes
configuration file provides correct EOL handling forgit
related commands and actionsWhen editing files
Trim trailing whitespaces
Single EOL at end of files
Use spaces for tabs (use tab size according to coding guidelines or existing file contents)
ClangFormat
To ensure consistent and readable code across the project, ClangFormat is recommended.
Note
The following guidelines are based on ClangFormat version 15.0.7
Installing ClangFormat
To install ClangFormat 15.0.7, execute the following command depending on the operating system.
pacman -S mingw-w64-x86_64-clang
apt -y install clang-format
Configuring ClangFormat
To configure ClangFormat, create a .clang-format file in the root directory of your project. Below is the configuration used in openPASS (Open Source):
--- BasedOnStyle: Google AccessModifierOffset: -2 AllowShortFunctionsOnASingleLine: Inline AlignOperands: AlignAfterOperator BinPackArguments: false BinPackParameters: false BreakBeforeBraces: Allman BreakBeforeBinaryOperators: All ColumnLimit: 120 SpacesInLineCommentPrefix: Minimum: 0 Maximum: 1 CommentPragmas: '^\\.+' IncludeCategories: - Regex: '^((<|")(gtest|gmock)/)' Priority: -1 - Regex: '^<[^Q]' Priority: 1 - Regex: '^<Q' Priority: 2
Running ClangFormat
To format the code using ClangFormat, run the following command in the terminal:
clang-format -i [source_file(s)]
Replace [source_file(s)] with the path(s) to the file(s) to format. The -i option tells ClangFormat to modify the files in-place.
ClangTidy
Supported Version: 14.0.6
To ensure code quality and adherence to coding standards, ClangTidy is recommended.
The used checks are located in the .clang-tidy
file, where lines starting with -
are checks that have been deactivated.
For more details, visit the ClangTidy official page.
Commit Message Guidelines
Overview
This section outlines the guidelines for writing commit messages in openPASS repository. Following these guidelines ensures that commit messages are clear, descriptive, and help facilitate collaboration among team members. This section uses excerpts from Conventional Commits licensed under CC BY 3.0 by it’s authors.
Commit Message Format
Each commit message should consist of a single short summary line (recommended, up to 50 characters) followed by a more detailed description (if necessary). The message should adhere to the following format:
<type>[optional scope]: <description> [optional body] [optional footer(s)]
The
<type>
part represents the type of the commit, which helps in categorizing the nature of the changes. The following types are allowed:
feat
: A new feature or enhancement.
fix
: A bug fix.
docs
: Documentation-related changes.
style
: Code style changes (e.g., formatting, spacing).
refactor
: Code refactoring without adding new features or fixing bugs.
test
: Adding or improving tests.
chore
: Maintenance tasks, build changes, or other non-functional modifications.
ci
: Changes related to CI.
build
: Modifications related to build step.
perf
: Modifications related to performance improvements.
revert
: Revert any code changes.The
<optional scope>
section is optional but is used to provide additional contextual information and is contained within parenthesis.The
<description>
is a brief description of the changes made in the commit. It should be concise yet informative and is recommended to not exceed 50 characters.The
<optional body>
section is optional but recommended, especially for complex changes or when further explanation is needed. This section should provide additional context, justification, and details about the changes made. Use bullet points for better readability when necessary.The
<optional footer>
section is also optional but can be used to provide supplementary information related to the commit.
Header File Inclusion
Overview
When working on a C/C++ project, it’s essential to include header files correctly. This documentation explains the various ways to include header files, depending on their source.
System Libraries
Header files from system libraries should be enclosed in angular brackets (< >). This syntax informs the compiler to search for the headers in the system’s standard include directories.
#include <stdio.h> #include <stdlib.h>
Dependencies in CMAKE_PREFIX_PATH
If the header files are from dependencies that are part of the CMAKE_PREFIX_PATH, use angular brackets (< >) as well. This indicates to the compiler that the headers are part of external dependencies.
#include <dependency/header.h>
Repository Header Files
If the header files are from project’s repository then, use double quotes (” “”).
#include "my_component/header.h"