Coding Standards

Revision History

Identifier

Release date

Description

v0.1 (Baseline)

03/31/2026

Initial CML coding standards

v0.2

07/21/2026

Changed GitLab references to GitHub and converted to reStructuredText

Approvers

Prepared by

Approved by

Nino Tarantino
CML Maintainer
03/31/2026
Daniel Jordan
CML Lead
03/31/2026

Introduction

This document provides the formal code standards that are used within the Common Model Library (CML) team. The coding standards in this document are designed to protect the reliability, maintainability, and usability of the library while avoiding overly restrictive standards that may prevent some simulation teams from easily contributing their models to CML. These standards are written based on generally accepted best practices in industry as well as lessons learned from experienced developers in the Trick-based simulation field at NASA JSC. These standards are expected to mature and develop over time.

Purpose

Coding standards are used in large software development projects because they provide multiple benefits to the organization developing the software application. These benefits are seen as critical for the CML team developing and maintaining complex and high-fidelity time-domain simulation models used for spacecraft analysis.

Scope

The coding standards listed in this document apply only to the developed code associated with models under the control of the CML team. These coding standards do not apply to external packages such as Trick, JEOD, or any other third-party dependency.

Change Authority/Responsibility

Proposed changes to this document shall be submitted as a GitHub issue or via email to the CML team for consideration and disposition with the team lead.

Applicable Documents

The following documents include specifications, models, standards, guidelines, handbooks, and other special publications. The documents listed in this product are applicable to the extent specified herein.

Document Number

Document Revision

Document Title

NASA-STD-7009

A.1

Standard for Models and Simulations

NPR 7150.2

C

NASA Software Engineering Requirements

Reference Documents

The following documents contain supplemental information to guide the user in the application of this document.

Document Number

Document Revision

Document Title

Coding Standards

This section describes the coding standards and how they apply to the software development workflow. The purpose of having coding standards is to ensure that a project's code base not only functions correctly but is also readable modifiable, and maintainable. The code that comes into the library must be easily reviewable and not threaten the stability of the library itself. With these goals in mind, the CML Coding Standards fall in two categories:

  • Model Coding Standards – These coding standards should be met upon a developer’s Pull Request Review. These standards are intended to ensure the quality, stability, and cohesiveness of CML. Non-compliances will be identified in the review and evaluated for risk to integration into the library.

  • Best Practice Coding Standards – These coding standards should be met as early as possible but are not required to be met upon a developer’s Pull Request Review. These standards are intended to ensure that the codebase follows modern best practices. Non-compliances will be evaluated for risk to the library and documented in a follow-on GitHub issue for future resolution if necessary.

Application and Enforcement

New models submitted to CML must first pass through a Pull Request Review. During the review, the submitting group provides CML with the NASA NPR 7150.2 classification of the model and evidence of NASA-STD-7009 compliance. The CML team will review the documentation provided and will check the models submitted for adherence to the coding standards. Many of the model coding standards are checked with assistance from automated tooling, which reduces the amount of manual review necessary.

Updates to existing CML code will also be checked for adherence to the coding standards during a Pull Request Review. Unlike a new model submission, NPR 7150.2 and NASA-STD-7009 documentation is not required unless the model’s classification has changed.


Model Coding Standards

These standards cover the attributes of the source code required for CML models and must be met before acceptance of the source code into the main branch of the CML codebase.

Model Coding Standards are broken into categories depending on the language used. CML-MCS-GENERAL standards apply to all code, regardless of language. CML-MCS-CPP standards apply to C++ code. CML-MCS-PYTHON standards apply to Python code.


CML-MCS-GENERAL-1: All Trick-based simulation model code shall be written in the C++ programming language

Rationale: Trick simulation models should be written in C++. Other programming languages, such as C, are not allowed to be used for model implementation. Autocoded models from MATLAB or Simulink source are not considered to have been written in C++.

Enforcement: Static analysis and Pull Request Review.


CML-MCS-GENERAL-2: All scripts required to maintain model code must be committed at the time of Pull Request Review

Rationale: Some models may contain data or other content that was automatically generated by means of a script. These scripts must also be committed and live alongside the model so that the model may be properly maintained.

Enforcement: Pull Request Review.


CML-MCS-GENERAL-3: Source code shall not contain ITAR, EAR, or CUI data

Rationale: CML is an open-source project and must not contain sensitive data.

Enforcement: Pull Request Review.


CML-MCS-GENERAL-4: Source code shall be formatted in accordance with a common stylesheet

Rationale: Consistent codebases are easier to use and maintain. Automated code formatting ensures that the git history contains only impactful changes to the code rather than formatting tweaks. The specific formatting enforcement tool and stylesheet may differ between languages.

Enforcement: Static analysis operating off of a common stylesheet available to developers and users.


CML-MCS-GENERAL-5: Commented-out code shall only be allowed when accompanied by an associated project issue, point of contact email address, and current date

Rationale: Commented-out code should be rare. When it is included in the codebase, there should be an expectation that the code will be un-commented or removed by a certain date.

Enforcement: Pull Request Review.

Example

// TODO jane.doe@nasa.gov 01/01/2000: uncomment when addressing issue #1.
//my_type.nonexistent_field = 1;

CML-MCS-CPP-1: Source code shall live within the “cml” C++ namespace

Rationale: Namespaces prevent name collisions between CML-defined types and the types defined by consumers of the CML library.

Enforcement: Pull Request Review.

Example

namespace cml {

struct MyType {
};

void my_function(int my_param);

}

CML-MCS-CPP-2: Header files shall direct Trick to place generated interface code in the “cml” Python module via the Trick header “PYTHON MODULE” directive

Rationale: Trick provides the option to generate Python interface code into a specific Python module rather than in the global “trick” scope. This prevents name collisions between CML-defined types and the types defined by Trick or consumers of the CML library.

Enforcement: Static analysis.

Example

/* PURPOSE: (My purpose)
 *
 * PYTHON_MODULE: (cml)
 */

CML-MCS-CPP-3: Source code shall use the .hh file extension for headers and the .cc file extension for source files

Rationale: Consistent codebases are easier to use and maintain.

Enforcement: Static analysis.


CML-MCS-CPP-4: Functions and types limited in scope to the implementation details of a module shall be placed in an unnamed namespace within the corresponding module source file

Rationale: Exposing internal implementation details in public headers slows down Trick interface code generation and may confuse users. Unnamed namespaces are the modern equivalent to static functions and types declared at the file-level.

Enforcement: Pull Request Review.

Example

// Within myfile.cc
namespace {

void some_local_function() {
}

}

CML-MCS-CPP-5: Structs shall be used only for passive objects with all public fields that have no invariants

Rationale: Structs are widely understood by the C++ community to carry data with no invariants. Although structs may have protected or private fields, if such encapsulation is necessary, then classes should be used.

Enforcement: Pull Request Review.

Examples

struct JustSomeData {
    int int_data {};
    double double_data {1.0};
    std::string string_data {"Some Data"};
};

class EncapsulationNecessary {
public:
    void set_coefficient_of_friction(double coefficient_of_friction_in) {
        if (coefficient_of_friction_in >= 0.0) {
            coefficient_of_friction = coefficient_of_friction_in;
        } else {
            throw_some_error();
        }
    }

private:
    double coefficient_of_friction {};
};

CML-MCS-CPP-6: Source code shall compile with no warnings

Rationale: Compiler warnings signify that something may be wrong with the code and should rarely be ignored.

Enforcement: Automated builds in GitHub Actions treat warnings as errors.


CML-MCS-CPP-7: Source code shall pass review by linters without generating any warnings

Rationale: Linters such as cppcheck and clang-tidy are widely used in industry and provide meaningful feedback on potential code quality issues. These warnings should rarely be ignored.

Enforcement: Linters are run in a GitHub Action and produce a failing result upon detecting an error.


CML-MCS-CPP-8: Source code shall have associated unit tests which cover at least 90% of lines with meaningful tests

Rationale: Inadequately tested code is prone to introducing regressions and is not fit for use within high-fidelity spacecraft simulations.

Enforcement: Manual review of code coverage artifacts generated in a GitHub Action during Pull Request Review.


CML-MCS-CPP-9: Source code shall compile using the ISO/IEC 14882 C++17 standard

Rationale: A reasonably recent version of the C++ language should be used by all models to leverage new language features and maintain interoperability with other open-source libraries.

Enforcement: All toolchains use the minimum supported C++ standard.


CML-MCS-CPP-10: Source code shall have associated documentation which includes, at minimum, the model’s public API, a users’ guide, assumptions and limitations, and details about prior verification and validation activities

Rationale: Code without documentation cannot be effectively maintained or used.

Enforcement: Pull Request Review.


CML-MCS-PYTHON-1: Source code shall not call exec(), eval(), or otherwise evaluate an arbitrary string as Python code

Rationale: Exceptions thrown within code evaluated by exec() or other related functions do not provide meaningful debugging information. These functions also introduce security concerns into the codebase. Use modules and functions instead of exec(open()).

Enforcement: Pull Request Review.

Example, wrong

exec(open("Modified_data/utils.py").read())
some_function_from_utils()

Example, correct

from Modified_data.utils import some_function_from_utils
some_function_from_utils()

CML-MCS-PYTHON-2: Methods which accept keyword arguments shall document all allowable keyword arguments

Rationale: Users should not have to read implementation details to determine which keyword arguments are accepted by a function.

Enforcement: Pull Request Review.

Example

def myfunc(*args, **kwargs) -> None:
    """Does a few things.

    Keyword arguments:
    ------------------
    foo : An instance of Foo
    bar : A numeric type such as an int or float
    baz : A string-like type
    """
    implementation(*args, **kwargs)

Best Practice Coding Standards

These standards cover best practice for the code within CML. These standards are not required to be met at the time of integration into the main CML branch but should be met as soon as possible afterwards. Like the Model Coding Standards, CML Best Practice Coding Standards are grouped by programming language.


CML-BP-CPP-1: Do not define macros

Rationale: Macros cannot be put into a namespace and can be difficult to debug. Use function templates and inline variables instead.

Example, wrong

#define ADD_ONE(input) ((input) + 1)

#define SPEED_OF_LIGHT 299792458.0

Example, correct

template <typename Type>
[[nodiscard]] constexpr Type add_one(const Type& input) {
   return input + 1;
}

inline constexpr double SPEED_OF_LIGHT = 299792458.0;

CML-BP-CPP-2: Do not invoke undefined behavior

Rationale: The outputs of a program which invokes undefined behavior are suspect.

Note: Most undefined behavior will be caught by static analysis tools and will be required to be addressed during Pull Request Review.


CML-BP-CPP-3: Do not use global variables

Rationale: Global variables often lead to “spaghetti code” which is difficult to maintain and understand.


CML-BP-CPP-4: Do not use the “new” or “delete” keywords

Rationale: The Trick Memory Manager should be used to allocate memory which must be logged or otherwise available for Trick-specific purposes. Otherwise, smart pointers provided by the C++ standard library should be used for dynamic memory management. Both of these options provide automated cleanup of the allocated memory.

Example, wrong

auto* data = new double;

Example, correct using the Trick memory manager

auto* data = static_cast<double*>(trick_TMM->declare_var("double"));

Example, correct using smart pointers

auto data = std:make_unique<double>();

CML-BP-CPP-5: Do not allocate significant memory in scheduled simulation jobs

Rationale: Trick scheduled jobs are often intended to be run at high frequencies for high-fidelity spacecraft analysis. Frequently reallocating memory during such jobs introduces performance bottlenecks and is a symptom of bad design. Some reallocation may be expected during certain simulation events, but most memory allocation should occur during simulation initialization.


CML-BP-CPP-6: Favor composition over inheritance

Rationale: Frequent use of inheritance can make a codebase difficult to understand. Often, composition allows for easier code maintenance and testability.


CML-BP-PYTHON-1: Use docstrings

Rationale: Python docstrings help users use Python code correctly and are recommended by PEP 257.

Example

def foo(bar) -> None:
    """Foos a bar."""

CML-BP-PYTHON-2: Use type annotations

Rationale: Type annotations help address one of the biggest shortcomings of dynamically typed languages, where the types allowed as inputs or expected as outputs from functions are not always easy to deduce.

Example

def connect(port: int, hostname: str) -> StatusCode:
    """Attempt to connect to a port on a host."""
    return implementation(port, hostname)

CML-BP-PYTHON-3: Functions should always return the same number of items, preferably only one item

Rationale: Functions which return a variable number of arguments depending on the logic path taken are brittle and require users to understand the inner workings of the function which they are accessing.


CML-BP-PYTHON-4: Do not use classes in code intended for use in Trick input files

Rationale: Classes are designed to hold state and provide access control to data, while Trick input files are designed to be a purely procedural interface to a simulation. Frequent overuse of classes in Trick input files has proven repeatedly to negatively impact code usability and maintainability. Use free functions instead.


Coding Standards Waiver

Waivers to any coding standard may be granted on a case-by-case basis when it can be demonstrated that the following criteria are both met: 1. Safeguards are in place to ensure that the exception does not create a risk to the overall project. 2. The effort required to bring the code to a satisfactory standard would be excessive.

The request for a waiver is made during Pull Request Review. The request may be in the form of a PowerPoint presentation, a memo, or any other format capable of conveying the following information: - Violation (with code) - Options for mitigation/resolution - Rationale why the violation is acceptable - Evaluation of risk to accepting the waiver

If the waiver is granted, the request must be updated to reflect the approver, date of approval, and this information must be recorded with the model documentation. The complete list of waivers will be maintained separately for CML maintenance and metrics purposes. If the waiver is denied, the developer is directed to resolve the violation.

Appendix A: Acronyms and Abbreviations

Acronym

Abbreviation

CML

Common Model Library

CUI

Controlled Unclassified Information

EAR

Export Administration Regulations

ITAR

International Traffic in Arms Regulations

JEOD

Johnson Space Center Engineering Orbital Dynamics

JSC

Johnson Space Center

Appendix B: Glossary of Terms

Term

Description

Trick

An open-source C++/Python driven simulation development framework. See https://github.com/nasa/trick for more information.

Pull Request Review

When code is ready to be reviewed and accepted into the main production branch of CML, a pull request is opened. The Pull Request Review is the process by which the code is assessed for compliance with CML's code standards and other NASA standards by the CML team.