Skip to content

Code guidelines

Mike Tetley edited this page Apr 24, 2023 · 37 revisions

Python

All Python code should where possible follow the PEP 8 - Style Guide for Python Code.

A quick reference is provided below for some of the most commonly used examples:

Naming conventions

Overriding Principle

Names that are visible to the user as public parts of the API should follow conventions that reflect usage rather than implementation.

Package names

Python packages should have short, all-lowercase names. The use of underscores is discouraged as per PEP 8, however they can be included only if required to improve readability.

Examples:

  • mypackage
  • my_complex_package_name

Module names

Module names should be short, all-lowercase, and ideally semantic in nature. Underscores can be used in the module name if it improves readability as per PEP 8.

Examples:

  • mymodule
  • my_module
  • my_more_complex_module

Class names

Class names should be short, ideally semantic in nature, and normally use the CapWords convention as per PEP 8.

Example:

  • MyNewClass

Function and method names

Function names should be lowercase and ideally semantic in nature with words separated by underscores as necessary to improve readability as per PEP 8.

Examples:

  • my_function
  • my_more_complex_function

Variable names

Variable names should be lowercase and ideally semantic in nature, with words separated by underscores as necessary to improve readability as per PEP 8.

Example:

  • my_variable
  • my_more_complex_variable

Note: Never use the characters ‘l’ (lowercase letter el), ‘O’ (uppercase letter oh), or ‘I’ (uppercase letter eye) as single character variable names. In some fonts, these characters are indistinguishable from the numerals one and zero. When tempted to use ‘l’, use ‘L’ instead.

Documentation

Overriding Principle

Documenting software is very important! Documentation helps both users and developers to understand everything about a given piece of software or code. From more high-level aspects such as what is the purpose of the code, how it is put together and how it is deployed, to more low-level information including installation, troubleshooting and how the code can be implemented and/or extended.

Comments

If a line of code does something, describe it with a comment! Comments should be complete sentences and be placed on the line above the line of code they are describing. The first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!). Comments that contradict the code are worse than no comments. Always make a priority of keeping the comments up-to-date when the code changes!

Block comments

Block comments generally apply to some (or all) code that follows them, and are indented to the same level as that code. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment). Paragraphs inside a block comment are separated by a line containing a single #.

Inline comments

Use inline comments sparingly.

An inline comment is a comment on the same line as a statement. Inline comments should be separated by at least two spaces from the statement. They should start with a # and a single space.

See PEP 8 - Comments for a full description of good commenting practices.

Docstrings

A docstring (or documentation string) is a string literal that occurs as the first statement in a module, function, class, or method definition. This docstring becomes the __doc__ special attribute of that object. All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. A full description of general docstring best practices can be found in the PEP 257 - Docstring Conventions.

Beyond providing code-level information to the user via the __doc__ special attribute, docstrings can (and should) also be used to auto-generate package/API reference documentation. For this task, it is recommended to use Sphinx.

To auto-generate documentation using Sphinx, specific docstring formatting is required (i.e. you cannot use PEP 257 - Docstring Conventions formatting). For this, please use the numpydoc syntax. Documentation should use the sphinx-rtd-theme found here.

Example Sphinx-compatible numpydoc formatting for a multiline docstring describing a function containing multiple explicit arguments:

def my_function(arg1, arg2, arg3=True):

    """
    Clear and concise function description.

    Parameters
    ----------
    arg1 : string
           Argument 1 description
    arg2 : float
           Argument 2 description
    arg3 : bool, default True
           Argument 3 description

    Returns
    ----------
    string
        Description of returned object
    """

    if type(arg1) == str and type(arg2) == float and type(arg3) == bool:

        result = 'winning'
  
    else:

        result = 'not winning'

    return result

Testing

Overriding Principle

Robust and transparent software testing is a very important phase of the complete development cycle. Routinely testing classes, functions and scripts not only ensures that code is working correctly, it also informs code optimisation.

Unit testing

To do this efficiently, unit testing is considered an industry-standard approach to evaluate Python code stability and performance.

For testing Python code at ACESS-NRI, it is recommended that unit testing be completed using the pytest framework. A library of pytest examples can be found here.

Fortran

R

C/C++

Clone this wiki locally