Coding Conventions¶
Having consistent coding conventions ensures consistency and maintainability of the code. As such, developers are expected to follow the rules/best practices detailed below when working on the codebase. Note that there is a separate page for CI guidelines for any work done on the CI-related code.
It should be noted that CTA is a large software package containing a significant amount of older code. As a result, not all of the current codebase is following these conventions and best practices. That is of course not reason to ignore these for any new additions; see them as standards to live up to. We are continuously trying to improve the existing code base while we are adding features.
Classes & Files¶
File Organization¶
- One class per file.
- The class name and its filename should match exactly. Filenames are PascalCase.
- Use
*.cpp
for implementation files and*.hpp
for header files. - Use
#pragma once
in each header file to prevent multiple inclusions. - Group related files into directories to improve project structure and navigation.
Class Design¶
- Follow the single responsibility principle: each class should do one thing and do it well.
- Keep classes short (ideally < 200 lines excluding comments). This should be a natural result of the single responsibility principle.
- Favor composition over inheritance to enhance code reusability and flexibility.
- Decouple the interface from the implementation (to keep the codebase modular).
- Use explicit constructors to avoid implicit type conversions.
- Use
override
andfinal
keywords to indicate method overrides and prevent further overriding. - Avoid exposing member variables; use getter and setter methods instead.
- Follow the Rule of Five (or Rule of Zero) to manage resource copying and movement.
Method Design¶
- Follow the single responsibility principle: each method should perform one task.
- Keep methods short (ideally < 20 lines). This should a natural result of the single responsibility principle.
- Ensure methods are const-correct: use
const
wherever possible. - Prefer passing by reference or pointer for large objects to avoid unnecessary copying.
- Avoid side effects in methods; try to write pure functions wherever possible.
General Principles¶
- Aim for code readability and clarity over cleverness or brevity.
- Prefer static polymorphism (templates) over dynamic polymorphism (inheritance and virtual functions) where possible.
- Use Resource Acquisition Is Initialization (RAII) to manage resource lifetimes.
- Avoid premature optimization; focus on clean, readable, and maintainable code. Modern compilers are proficient at optimization.
- Make base class destructors
public virtual
to ensure proper cleanup in derived classes. - Define and initialize variables in the order of declaration.
- Ensure all exceptions are properly handled or propagated.
- Do not use
using
directives in header files or before#include
statements to avoid namespace pollution. - Do not call virtual methods in constructors and destructors to avoid unexpected behavior.
- Do not cast away
const
as it can lead to undefined behavior. - Avoid global data unless absolutely necessary.
- Avoid raw pointers; prefer smart pointers (e.g.,
std::unique_ptr
,std::shared_ptr
). - Avoid macros; use inline functions,
constexpr
, or templates instead. - Avoid magic numbers; use named constants with descriptive names.
- Avoid excessive nesting.
- Minimize variable scope.
Formatting¶
- Follow the formatting rules defined in
.clangformat
. This is automatically checked by the CI. - When implementing namespaced entities within a cpp file, put the necessary surrounding namespace {} clauses. The contents of a namespace clause should not be indented.
Documentation¶
- Use the Doxygen Javadoc style for all class and method comments.
- Each class should have a top-level Doxygen comment describing its purpose and usage.
- Each method should have a Doxygen comment describing its functionality.
- Ensure names of classes, methods, parameters, and variables are descriptive, meaningful, and unambiguous.
- Write self-documenting code; use comments sparingly to clarify intent or document complex algorithms.
- Where useful, document the "why" of the code.
Other¶
Include Directives¶
- Use forward declarations wherever possible to reduce dependencies and compilation times.
-
Use <> for standard and external headers and "" for project headers:
-
Use full paths from the project root for project includes; avoid relative paths.
Copyright¶
- Add a copyright comment at the top of each file with the following text (make sure to replace the year accordingly):
The CERN Tape Archive (CTA)
Copyright © 2024 CERN
This program is free software, distributed under the terms of the GNU General Public Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can redistribute it and/or modify it under the terms of the GPL Version 3, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
In applying this licence, CERN does not waive the privileges and immunities granted to it by virtue of its status as an Intergovernmental Organization or submit itself to any jurisdiction.