CMS Naming, Coding, And Style Rules
By the CMS Ofﬂine Software Development Team
This document describes the design, naming, coding, and style rules and recommendations for CMS software written in C++, plus a few guidelines for Python configuration.
1 – Introduction
This document describes the CMS C++ software naming, coding, style, and documentation rules and recommendations.
All CMS C++ software is expected to comply with the rules. The asterisk (*) after some rules indicates that there may be exceptional use cases where the rule may be violated with good justiﬁcation. Intentional violations must be documented in the code next to the violation.
Coding rules are meant to prevent serious problems in software function, performance, maintainability, usability, and portability. The Packaging Rules section also has some brief guidelines for Python configuration.
2 – Naming Rules
- C++ header ﬁles use the sufﬁx .h, e.g.
- For C++ source ﬁles, the preferred sufﬁx is .cc, e.g.
- For a header file that contains a class, name that ﬁle after the class.
- Name source ﬁles after the class.
- A geometry XML file should be named as follows:
A revision to a file that has already been in use and that needs to be preserved requires a new version of the file with an incremented version number (“v2” in the example). On the other hand, an upgrade of the detector would require a new
physical_version_key. For example, an upgraded GEM might become:
- For class, struct, type, and enumeration names use upper class initials, e.g.
- For namespaces use lower case, e.g.
- Start method names with lowercase, use upper case initials for following words, e.g.
Allowed exception: Implementation of virtual methods inherited from external packages, e.g.
ProcessHits() method required by Geant4.
- Start data member names with lower case. A trailing “_” is the preferred method to distinguish a data member from the getter method (e.g.
- Using “set” for a setter method is preferred, e.g.
- For a getter method, using the value name is preferred, e.g.
- Do not use single character names, except for loop indices.
- Do not use special characters, except for “_” where allowed.
- Do not use “_” as ﬁrst character, except for user-defined suffixes (used in user-defined literals). Only use it as the last character for class data member names, not local variable names.
- Do not use “__”.
- Use clear and explanatory variable names.
3 – Style Rules
- Do not indent pre-processor directives – there should be no leading spaces before a directive. (*)
- Never change the language syntax using
- Do not use spaces between a function, constructor, or method name and its opening parenthesis, e.g.
energy() rather than
energy (). A similar style is encouraged but not required when brace initialization is used, e.g.
- Do not use spaces in front of  or on either side of -> . For example,
position[i] instead of
- Separate expressions in a
for statement by including a space after each semicolon.
- Use the same indentation for comments as for the block the comments refer to.
4 – Technical Coding Rules
- Protect each header ﬁle from multiple inclusion with:
(body of header file)
If necessary to create a unique name, one can add the directory name:
- Each header ﬁle contains one class declaration only. (*)
- Header ﬁles must not contain any implementation except for class templates and code to be inlined.
- Do not inline virtual functions.
- Do not inline functions which contain control structures which require block scoping.
- In your own packages, use forward declarations if they are sufﬁcient.
- Do not forward-declare an entity from another package.
- Do not use absolute directory names or relative ﬁle paths in
nullptr, not “0” or “NULL”. (*)
- Use types like
ptrdiff_t consistently and without mixing them.
- Use the
bool type for booleans.
- Copy and move assignment operators should return a reference to
- For a class, definition of any of the following requires definition of all five: destructor, copy constructor, copy assignment operator, move constructor, and move assignment operator. (*)
- Do not use function-like macros.
- Use C++ casts, not C-style casting. (*)
- Do not use the ellipsis notation for function arguments, except for variable argument templates.
- Do not use union types. (*)
- If a class has at least one virtual method, it must have a public virtual destructor or (exceptionally) a protected non-virtual destructor.
- When a derived class function overrides a virtual function, always mark it with
- Pass by value arguments which are not to be modiﬁed and are built-in types or small objects; otherwise pass arguments of class types by reference or, if necessary, by pointer.
Allowed exception: If the function algorithm would benefit from using a move of the argument instead of a copy, pass the argument by value.
- Properly use rvalue references for temporary objects that will be moved.
- The argument to a copy constructor and to an assignment operator must be a
const reference, while the argument for a move constructor or move assignment operator must be an rvalue reference. (*)
- Do not let
const member functions change the state of the object. Any special exceptions to this rule must still maintain thread safety. (*)
- A function must never return or in any way give access to references or pointers to local variables (stack variables) outside the scope in which they are declared, and a
const member function must not give non-
const access to any data directly or indirectly held by the object.
- Each class may have only one each of public, protected, and private sections, which must be declared in that order. (*)
- Keep the ordering of methods in the header ﬁle and in the source ﬁle identical.
- Provide meaningful argument names in method declarations in the header ﬁle to indicate usage, unless the type fully describes the usage.
- Try to avoid excessively long lines of code that impair readability.
- Data members of a class must not be redeﬁned in derived classes since doing so hides the original data member and could create confusion between the original and redefined data members.
5 – Documentation Rules
- Always comment complex, tricky, or non-intuitive portions of code.
- When revising code, be sure to update and revise comments.
6 – Packaging Rules
- It is discouraged to have small packages (with couple of cc and header files).
- Functionality used by multiple packages should go in the
- Only header files that expose a public interface should go into the
- Include only files that are in the current directory, e.g.
or in the
.../interface directory, e.g
- Group code files into packages based upon their matching dependencies. Such dependencies can be on other CMSSW packages or, more importantly, external libraries.
- Put plugins (e.g. EDProducers, EDAnalyzers, etc.) into a
Package/Subpackage/plugins/ directory, with its dedicated
- Do not split plugins into header and source files. If you do split them, keep the header files in the
- All code used only by the plugins in
../plugins should also go under
SealPlugins.cc or any special files that just define plugins, except for template instantiations, are discouraged.
- Unit tests to test the functionalities of your Library and/or Plugins should go under
- Add test library/plugins in
.../test/BuildFile.xml for the common functionality used only by your unit tests.
- For unit tests which simply run
cmsRun your-cfg (to test your plugin), please use
<test name="..." command="cmsRun …"/> in your
- Unit tests should return a non-zero value from their main to indicate test failure. Successful tests should print nothing or a very small amount to the log file. Tests should not require a human to read their output to determine if they succeed or fail.
_cfi file should contain only the definition of one module, and possible Modifier (“era”) customizations on it. The module label should be the same as the
_cfi file name.
_cfi file should be left to be generated automatically with the
fillDescriptions(). When Modifier customizations are needed, the auto-generated label should have e.g. “Default” postfix and be imported+cloned to the desired name.
- A module/Task/Sequence/Path with a given name should be defined in exactly one
- All Modifier customizations on a module/Task/Sequence/Path should be applied on the same file that defines the module/Task/Sequence/Path.
- When one customizes an existing parameter in
Modifier.toModify(), or in assignment, explicit types on the right hand side should be avoided.
- To keep the repository size under control, we discourage adding any data files under
- Please use the cms-data externals GitHub repositories to add/change any data file.
Binaries and scripts
- Public executables/binaries should go under
- It is discouraged to generate plugins from
- Additional libraries used only by multiple executables of your
.../bin should also go under
- Any utilities which should be available publicly (i.e. in the PATH) should go under
.../bin and use the
INSTALL_SCRIPTS flag in
.../scripts directory is reserved for scripts that need to be available in the PATH. Configuration and data files should go into appropriate directories, like
7 – Design and Coding Guidelines
These guidelines are a brief summary of highlights from the C++ Core Guidelines by Bjarne Stroustrup et al. The links for each guideline provide explanations and justifications.
- Do not use mutable global data (no globals).
- Ensure code is thread-safe. Avoid non-constant shared data, like static variables (thread safety).
- Class data members that store a class invariant should be private (invariant data members).
- A collection of data values that can take any value should be a struct, not a class, and those data members should be public without getters and setters. (struct not class).
const all methods, data members, variables, and pointer or reference parameters that do not need to be non-const. Use
constexpr for all constant values that can be evaluated at compile time (const).
- Do not use magic numbers. Deﬁne constants using
enum class or
- For ownership of dynamic memory, don’t use bare pointers but rather smart pointers:
std::unique_ptr, std::shared_ptr, and
std::weak_ptr and their constructors
std::make_shared<T>() (smart pointers).
- Avoid inlining unless you are sure you have a relevant performance problem (inlining).
char * (string).
- Avoid use of C-style arrays in favor of STL containers (std::array).
- In general, do not catch exceptions – leave them to the Framework (see Exception Guidelines).
- Do not use the singleton pattern; use framework services (no singletons).
- Encapsulate algorithms and collaborating classes in namespaces (namespaces).
- Design functions that are short and simple and that perform a single, coherent, logical task (logical task, short functions).
- Do not duplicate code. If procedural code is needed in two or more places, create a function for the task and call it where needed. (functions, encapsulate)
- Do not use goto (no goto).