Introduction

The goal of this set of coding standards that can be automatically checked is to help you write consistent, clean, understandable and maintainable m-code. The resulting code will be more readable for both yourself and others. These guidelines are no strict rules that must be followed at all cost. They are simply there to help you write m-code well and you can deviate from them as you please.

Automatic compliance checking

Most of the coding standards described here can be checked using Code Checker for MATLAB by MonkeyProof Solutions. The checkable coding standards are indicated by this logo cc4m_logo_inline at the top. These coding standards are configured in the predefined MonkeyProofSolutions configurations set available with the tool. This set is the default selection after installing. For instructions on how to check your code against coding standards, see the video below. The steps are also described below the video.

You can check your code for compliance with the guidelines described here as follows:

  1. Install Code Checker for MATLAB. If you have not purchased the tool yet, you can do so here. Alternatively, you could request a free trial license there.
  2. Open Code Checker for MATLAB in one of two ways:
    • Click the shortcut created at the top of the screen next to the documentation search bar: .
    • Run monkeyproof.cc4m.start() from the command window.
  3. Select whether you want to check one or more files, all files in a folder, or all files in a MATLAB Project.
  4. Select what files/folder/project to check.
  5. Further customization is available, for example checking a folder including or excluding all subfolders.
  6. Click the Run button at the bottom to start checking your code.

The guidelines that require human judgment or are simply not possible to check statically in MATLAB are not part of this coding standard.

Structure of this document

The coding standards and guidelines are grouped under specific categories to help keep things organized:

  • Naming conventions: Guidelines in this chapter describe how variables, functions etc. can be named in a consistent and insightful manner.
  • Layout & comments: This chapter contains guidelines to help improve readability of your code for yourself and for others. There are guidelines on whitespace, comments and more.
  • Statements & expressions: The guidelines and coding standards in this chapter are about how to use constructs such as if/else blocks, what built-in functions or keywords to avoid, how to best structure your statements etc.
  • Higher level guidelines: This chapter contains (among others) coding standards on higher-level objects such as functions or files.

Guideline template

Every guideline is structured as follows:

Guideline name

IDA unique guideline identifier.
TitleBrief description of the guideline.
PriorityPriority of the guideline can be one of Mandatory, Strongly recommended and Recommended.
Severity levelSeverity level of the guideline can be in the range from 1 to 10. The most important ones are of severity level 1 and next levels are reserved for more pedantic issues. Each of the levels is described below.
DescriptionA more elaborate description of the guideline. Can include exceptions.
RationaleRationale or justification behind the guideline: why should you apply this guideline and how does your code improve when applying it or deteriorate when violating it?
Exception (Optional)An exception might apply to a guideline, i.e. a case for which the guideline does not hold.

Avoid:

One or more code examples to avoid using.

Instead use:

The example(s) above improved by complying with the guideline.

Severity levels

The following definition of the severity levels is used as a guide to make it easier to group the different guidelines and coding standards.

  • Level 1 - Programming error (no discussion)
  • Level 2 - Most likely a programming error (there are exceptions but in more than 50% of the cases this is a programming error)
  • Level 3 - Accidents waiting to happen (there is no error at the moment but if somebody makes a change the house of cards might collapse)
  • Level 4 - Important design issues
  • Level 5 - Less important design issues
  • Level 6 - Portability related rules, maintenance related issues
  • Level 7 - Performance related rules
  • Level 8 - Rules that deal with periphery such as comments, harmless preprocessor issues, etc.
  • Level 9 - Naming conventions related rules
  • Level 10 - Style related issue

As it currently stands, these severity levels have no further meaning in the Code Checker for MATLAB. They are however related to the severity levels of Tiobe's TICS tooling.

Naming conventions

The guidelines in this chapter describe how variables, functions etc. can be named in a consistent and insightful manner. If you wish to deviate from the casing guidelines (for example if you want your variable names snake_cased) at least make sure to apply consistent casing. Use the same casing scheme throughout your code so that classes, functions etc. can be easily identified by their name.

Name length cc4m_logo_inline

IDNAMING-1
TitleVariable names shall be at most 32 characters long. Function names shall be at least 3 and at most 32 characters long.
PriorityRecommended
Severity level9
DescriptionVariable names shall be at most 32 characters long. Function names shall be at least 3 and at most 32 characters long.
RationaleNames shall be descriptive, so should not be too short. However, variable names can sometimes be single characters (x, y) and still be descriptive. Names that are too long can reduce readability because they introduce long lines of code.

Avoid:

maximumValueOfTheEntireSetOfDataPoints = max(data);

Instead use:

maxData = max(data);

Loop iterator naming cc4m_logo_inline

IDNAMING-2
TitleIterator variables shall be prefixed with i, j, k etc.
PriorityRecommended
Severity level9
DescriptionIterator variable names shall be at least 3 characters long. In nested for-loops, the starting letters of the iterator names shall be subsequent letters in the alphabet.
RationaleIterator variables of for-loops are easily distinguishable from other variables by using these prefixes.

Avoid:

for nodeIdx = 1 : 10
    for j = 1 : 3
        myGraph(nodeIdx).plotIt(j);
    end
end

Instead use:

for iNode = 1 : 10
    for jPoint = 1 : 3
        myGraph(iNode).plotIt(jPoint);
    end
end

Negated boolean names cc4m_logo_inline

IDNAMING-3
TitleNegated boolean variable names shall be avoided.
PriorityStrongly recommended
Severity level9
DescriptionAvoid variable names including the word not.
RationaleReadability decreases when variables have negated boolean names, especially in combination with the ~ operator.

Avoid:

if ~notValid && isNotFound
    error('My error message.')
end

Instead use:

if isValid && ~isFound
    error('My error message.')
end

Parent / child name redundancy cc4m_logo_inline

IDNAMING-4
TitleNames of fields and properties shall not contain their parent's name.
PriorityRecommended
Severity level9
DescriptionNames of fields and properties shall not contain their parent struct or object's name.
RationaleWhen referenced, the fields and properties can have the same phrase multiple times in a row, which is unnecessary.

Avoid:

Beam.beamThickness
chair.weightOfChair

Instead use:

Beam.thickness
chair.weight

Name shadowing cc4m_logo_inline

IDNAMING-14
TitleFunctions and variables shall not shadow Mathworks-shipped functionality or other code.
PriorityMandatory
Severity level3
DescriptionFunctions and variables shall not shadow Mathworks-shipped functionality or other code. This includes MATLAB files (.m, .p, .mlapp, .mlx), mex-files (.mexw32 etc.) and Simulink files (.mdl, .slx).
RationaleShadowing code can result in unexpected behaviour, because it is unclear and not properly defined for example what function is called when multiple ones share the same name.

Names to avoid cc4m_logo_inline

IDNAMING-15
TitleNames of classes, functions, variables, properties and struct fields should not start with temp, my, etc.
PriorityRecommended
Severity level9
DescriptionNames of classes, functions, variables, properties and struct fields should not start with temp, my and they should not have names such as myClass, testFunction, etc.
RationaleNames like these do not properly indicate what the class, function or variable is for.

Function names document their use

IDNAMING-16
TitleNames of functions should document their use.
PriorityRecommended
Severity level9
DescriptionThe names of functions should document their use.
RationaleBy choosing a clear and descriptive name, the code becomes more readable.

Function name construction

IDNAMING-17
TitleA function name should consist of a verb and a noun.
PriorityRecommended
Severity level9
DescriptionAll function names shall consist of a verb followed by a noun.
RationaleThis way it is more likely to be clear what the function does and if there is no suitable name following this guideline, (for example because the function does more than one thing) the function may have to be refactored.

Name-value pair casing cc4m_logo_inline

IDNAMING-18
TitleName-value pairs shall be UpperCamelCased.
PriorityRecommended
Severity level9
DescriptionName-value pairs shall be UpperCamelCased (PascalCased) and contain no numbers, both when using the arguments block and when using the inputParser function.
RationaleConsistency in name-value pair naming improves readability of the code and predictability of calling syntax. Name-value pairs in MATLAB functions are UpperCamelCased as well.

Avoid:

function plotMeasurement(options)

arguments
    options.number_of_lines             = 3
    options.precision                   = 2.5
    options.SHOW_LEGEND (1, 1) logical  = true
end

...

end

Instead use:

function plotMeasurement(options)

arguments
    options.NumberOfLines               = 3
    options.Precision                   = 2.5
    options.ShowLegend (1, 1) logical   = true
end

...

end

Descriptive names

IDNAMING-19
TitleUse precise and descriptive names for functions, classes, packages and variables.
PriorityStrongly recommended
Severity level9
DescriptionUse precise and descriptive names for functions, classes, packages and variables.
RationaleThis increases the readability of the code.

Avoid:

function tk = convC2k(temp)

Instead use:

function temperatureK = convertCelsiusToKelvin(temperatureC)

The 'is' prefix

IDNAMING-20
TitleReserve the is prefix for logical values.
PriorityRecommended
Severity level9
DescriptionThe is prefix shall be used for functions returning logical values or properties and variables holding logical values.
RationaleThis increases the readability of the code as it is clear from the name of the function/property/variable what data type can be expected.

Abbreviations

IDNAMING-21
TitleDo not use abbreviations in variable names.
PriorityMandatory
Severity level9
DescriptionVariable names shall not contain abbreviations.
RationaleMaintain readability by not abbreviating words in your variable names. Common acronyms are allowed.

Avoid:

arrTim

Instead use:

arrivalTime

Units in variable names

IDNAMING-22
TitleDo not use units in variable names.
PriorityMandatory
Severity level9
DescriptionVariable names shall not contain units. Instead, add units as end-of-line comments in square brackets.
RationaleMaintain readability by using concise variable names.

Avoid:

accelerationInMillimetersPerSecondSquared = 1000;

Instead use:

acceleration = 1000; % [mm/s^2]

The 'n' prefix

IDNAMING-23
TitleThe prefix n should be used for variables that represent a number of things.
PriorityMandatory
Severity level9
DescriptionThe prefix n should be used for variables that represent a number of things. Do not use the prefix for other purposes and do not use other prefixes for representing the number of things.
RationaleVariables starting with this prefix can easily be identified.

Avoid:

numberOfFiles
nrCars
lineCount

Instead use:

nFiles
nCars
nLines

The 'test' suffix

IDNAMING-24
TitleReserve the suffix Test only for unit test filenames.
PriorityRecommended
Severity level9
DescriptionUse the suffix Test only for unit test filenames.
RationaleThis increases the readability of the code as it is clear from the name of the file that it is a unit test file.

Layout & comments

This chapter contains guidelines to help improve readability of your code for yourself and for others. The guidelines on indentation and whitespace make the code more visually appealing whereas guidelines on comments increase the usability of the code they reference. By using ample whitespace, your code will look clean and the more complicated statements maintain their readability.

Comment blocks cc4m_logo_inline

IDLAYOUT-1
TitleComment blocks shall not be used.
PriorityMandatory
Severity level8
DescriptionComment blocks (with %{ notation) shall not be used. Every first comment on a line shall start with a comment indicator (% or ...). Use CTRL-R and CTRL-T to comment/uncomment blocks of code.
RationaleConsistent comment syntax improves readability.

Avoid:

%{ This is a comment.
This is also a comment.
%}

Instead use:

% This is a comment.
% This is also a comment.

Function indentation cc4m_logo_inline

IDLAYOUT-2
TitleDo not indent functions on the root level of a file.
PriorityStrongly recommended
Severity level10
DescriptionOnly methods in a classdef file and nested functions shall be indented. This can be set as a preference in MATLAB.
RationaleHaving one less level of indentation makes for shorter lines of code, improving readability.

Avoid:

function computeWeight(in)
    weight = 2 * in;
end

Instead use:

function computeWeight(in)
weight = 2 * in;
end

Whitespace in statements cc4m_logo_inline

IDLAYOUT-3
TitleSurround operators with spaces.
PriorityStrongly recommended
Severity level10
DescriptionSurround the following operators with spaces:
= : ^ == <= >= < > ~= & && | || + - * .* /
Do not add a space between the unary minus-sign and its operand.
RationaleWhitespace around operators often leads to improved readability. As an exception, do not use spaces around the equals signs when using the Name=Value syntax introduced in MATLAB R2021a.

Avoid:

isValid=y>0&&x==-1;

Instead use:

isValid = y > 0 && x == -1;

Whitespace after characters cc4m_logo_inline

IDLAYOUT-4
TitleCommas, semicolons and keywords shall be followed by a space unless at the end of the statement.
PriorityStrongly recommended
Severity level10
DescriptionCommas, semicolons and keywords (for, while, if etc.) shall be followed by a space unless at the end of the statement.
RationaleA clear separation of keywords from other code improves readability.

Avoid:

while(ismember(x, [3,5,7,11,13]))
    x = x + 2;
end

Instead use:

while ismember(x, [3, 5, 7, 11, 13])
    x = x + 2;
end

Line length cc4m_logo_inline

IDLAYOUT-5
TitleLines shall be no more than 120 characters long.
PriorityStrongly recommended
Severity level10
DescriptionLines shall be no more than 120 characters long, including comments.
Use the MATLAB preference for displaying a vertical line at 120 characters. Comments can be automatically wrapped by setting a MATLAB preference.
RationaleA line of code should fit on a screen. Long lines of code are difficult to interpret and generally indicate great complexity.

Avoid:

theText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut luctus arcu ex, at viverra nibh malesuada ac. Proin vel arcu leo.';

Instead use:

theText = ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', ...
            'Ut luctus arcu ex, at viverra nibh malesuada ac. Proin vel arcu leo.'];

Indentation length cc4m_logo_inline

IDLAYOUT-6
TitleIndentation shall be four spaces long.
PriorityStrongly recommended
Severity level10
DescriptionIndentation shall be four spaces long. This is the default setting in the MATLAB editor.
RationaleUsing an adequate and consistent number of spaces for indentation improves readability and prevents unnecessary changes when others work on the code.

Avoid:

if x > 0
  if x < 2
    disp(x)
  end
end

Instead use:

if x > 0
    if x < 2
        disp(x)
    end
end

Comments on poorly written code cc4m_logo_inline

IDLAYOUT-7
TitleComments should not justify poorly written code.
PriorityStrongly recommended
Severity level8
DescriptionDo not use comments to justify or mock poorly written code.
Write proper code that requires no justification instead.
RationaleReadability will be improved if issues with the code are fixed immediately instead of documented in the comments.

Avoid:

x = 2;
y = 3 * x; % TODO: take z into account.

% FIXME: This piece of ugly code is copied from StackExchange.
z=[1,23,8.1]*(x^3.1415)*sqrt(y);

Instead use:

x = 2;
y = 3 * x + z; 

z = [1, 23, 8.1] * (x ^ 3.1415) * sqrt(y);

Equals sign alignment cc4m_logo_inline

IDLAYOUT-8
TitleAlign equals signs within a block of assignments.
PriorityRecommended
Severity level10
DescriptionAlign equals signs within the same block of assignments using proper indentation.
RationaleAligning equals signs improves readability.

Avoid:

carWeight = 1.7 * 600;
nWheels = 2 + 2;
maximumSpeed = 190;

Instead use:

carWeight       = 1.7 * 600;
nWheels         = 2 + 2;
maximumSpeed    = 190;

Commas in rows cc4m_logo_inline

IDLAYOUT-9
TitleUse commas to separate elements in a row.
PriorityRecommended
Severity level10
DescriptionUse commas to separate elements in a row. Place the comma directly after the element.
RationaleThis improves readability, especially in arrays of strings or character vectors.

Avoid:

fig.Position    = [0 1000 1.5 130];
saying          = ['An apple a ' period ' keeps the doctor away.'];

Instead use:

fig.Position    = [0, 1000, 1.5, 130];
saying          = ['An apple a ', period, ' keeps the doctor away.'];

Line continuation with operators cc4m_logo_inline

IDLAYOUT-10
TitleBinary operators in multi-line statements shall be placed at the start and not at the end of the line.
PriorityRecommended
Severity level10
DescriptionPlace binary operators in multi-line statements at the start and not at the end of the line.
RationaleBy placing binary operators at the start of the line, it is immediately clear what the line does.

Avoid:

isDone = isImplemented && ...
    isTested && ...
    isDocumented;

Instead use:

isDone = isImplemented ...
    && isTested ...
    && isDocumented;

Methods/Properties blocks with duplicate attributes cc4m_logo_inline

IDLAYOUT-11
TitleCombine multiple blocks of properties or methods with equal attributes into one.
PriorityRecommended
Severity level10
DescriptionCombine multiple properties and methods blocks with equal attribute values into one. Do not set attributes to their default values.
RationaleHaving multiple blocks with the same attributes is unnecessary and decreases the readability of classdef files.

Avoid:

classdef Rocket
    properties (Access = public, Hidden = false, Constant)
        Fuel = "Nuclear"
    end
    
    properties (Constant = true)
        Capacity = 2
    end
end

Instead use:

classdef Rocket
    properties (Constant)
        Fuel = "Nuclear"
        Capacity = 2
    end
end

Whitespace in statements cc4m_logo_inline

IDLAYOUT-12
TitleDo not use whitespace at the end of a line.
PriorityRecommended
Severity level10
DescriptionTo keep things clean, do not use white space at the end of a line of code unless it is followed by a comment.
RationaleThis prevents smart-indenting a file from inducing changes to those lines.

Help text

IDLAYOUT-13
TitleWrite header comments providing user documentation.
PriorityRecommended
Severity level8
DescriptionWrite header comments with text markup to provide user documentation useful both in-file and when using the help and lookfor functions. Optionally add syntax and see also sections.
RationaleThis increases readability, and makes the code more likely to be found and less likely to be reinvented.

Avoid:

function [avg, maxSize] = measureSize(obj, dim)
avg = mean(obj.Size, dim);
maxSize = max(obj.Size, dim);
end

Instead use:

function [avg, maxSize] = measureSize(obj, dim)
%MEASURESIZE Computes the size of the Item object.
%
% Input:
%   obj         The Item object.
%   dim         Dimension to measure.
%
% Output:
%   avg         Average size of the item.
%   maxSize     Maximum size of the item.

avg     = mean(obj.Size, dim);
maxSize = max(obj.Size, dim);
end

Whitespace around blocks of code

IDLAYOUT-14
TitleSeparate blocks of code by one or more blank lines.
PriorityRecommended
Severity level10
DescriptionSeparate coherent blocks of code by one or more blank lines.
RationaleIncreases the readability of the code.

Avoid:

deltaX          = mean(xIn);
xOut            = xIn - deltaX;
scalingFactor   = newZ / currentZ;
xOut            = xOut .* scalingFactor;
xOut            = xOut + deltaX;

Instead use:

% Shift to origin.
deltaX  = mean(xIn);
xOut    = xIn - deltaX;

% Calculate scaling.
scalingFactor   = newZ / currentZ;
xOut            = xOut .* scalingFactor;

% Shift back.
xOut = xOut + deltaX;

Correct spelling

IDLAYOUT-15
TitleUse correct spelling and punctuation in comments and write in complete sentences.
PriorityRecommended
Severity level8
DescriptionUse correct spelling and punctuation in comments and write in complete sentences, starting with a capital letter and ending in a period.
RationaleThis increases the readability of code. Error-strewn and poorly constructed comments reflect on the code they accompany.

Avoid:

% get sclaing factor
scaling_factor = new_z / current_z;
x_out = x_out * scaling_factor; % now recslaed

Instead use:

% Get the scaling factor.
scalingFactor = newZ / currentZ;
xOut = xOut * scalingFactor; % Now rescaled.

Align struct definition

IDLAYOUT-16
TitleKeep name-value pairs aligned in a struct declaration.
PriorityRecommended
Severity level10
DescriptionWhen defining a struct, align the names and values of the struct fields.
RationaleThis improves readability of the code by making it clearer what fields are defined and by what values.

Avoid:

s = struct("name", "Albert", "age", 2021 - 1979, "isValid", ismember("Albert", allNames));

Instead use:

s = struct(...
    "name",     "Albert", ...
    "age",      2021 - 1979, ...
    "isValid",  ismember("Albert", allNames))

Statements & expressions

The guidelines in this chapter are about how to use constructs such as if/else blocks, what built-in functions or keywords to avoid or how to best structure your statements. Following these guidelines will ensure the individual statements in your code are complete and easy to read.

Constant definitions at top cc4m_logo_inline

IDSTAT-1
TitlePlace constant definitions at the top of the function.
PriorityRecommended
Severity level10
DescriptionConstant definitions shall be placed at the top of the function, after defining global/persistent variables.
RationaleThat way they can easily be found and identified.

Avoid:

function testConstants(x)
y = 3 * x;
MAX_Z = 100;
z = min(y, MAX_Z);
end

Instead use:

function testConstants(x)
MAX_Z = 100;

y = 3 * x;
z = min(y, MAX_Z);
end

Magic numbers cc4m_logo_inline

IDSTAT-2
TitleDefine and document numeric values as variables before using them in an expression.
PriorityStrongly recommended
Severity level6
DescriptionDo not use magic numbers in your expression. Define them as variables before using them.
RationaleThis encourages reuse and documentation of numerical constants and improves overall readability. As an exception, unit conversion (for example, multiplying by 1e6) can be directly applied.

Avoid:

for iPick = 1 : 52
    disp(randi(13));
end

Instead use:

DECK_SIZE   = 52;
N_VALUES    = 13;

for iPick = 1 : DECK_SIZE
    disp(randi(N_VALUES));
end

Function calls without inputs cc4m_logo_inline

IDSTAT-3
TitleAdd empty parentheses to function calls without input arguments.
PriorityStrongly recommended
Severity level10
DescriptionAdd empty parentheses to function calls without input arguments.
RationaleThis helps to emphasize the fact that they are function calls and not variables or properties.

Avoid:

x = rand * 2;

Instead use:

x = rand() * 2;

One statement per line cc4m_logo_inline

IDSTAT-4
TitleWrite one statement per line.
PriorityMandatory
Severity level10
DescriptionWrite at most one statement per line.
RationaleMaintain readability of your code by having each line of code do exactly one thing.

Avoid:

persistent x, y

for iNode = 1 : 3, x = x + iNode; disp(x); end

Instead use:

persistent x
persistent y 

for iNode = 1 : 3
    x = x + iNode;
    disp(x);
end

If else cc4m_logo_inline

IDSTAT-5
TitleEvery if shall have an else section.
PriorityStrongly recommended
Severity level10
DescriptionEvery if shall have an else section, even if it does not contain executable code.
RationaleBy including an else section, no execution paths are overlooked. Additionally, code coverage can be accurately reported because without else, it is unclear whether the if-condition is ever false.

Avoid:

if x > 0
    saveData()
end

Instead use:

if x > 0
    saveData()
else
    % Do not save data.
end

Switch otherwise cc4m_logo_inline

IDSTAT-6
TitleEvery switch shall have an otherwise section.
PriorityStrongly recommended
Severity level10
DescriptionEvery switch shall have an otherwise section, even if it does not contain executable code.
RationaleBy including an otherwise section, no execution paths are overlooked. Additionally, code coverage can be accurately reported because without otherwise, it is unclear whether it happens that none of the cases occur.

Avoid:

switch reply
    case "Yes"
        saveData()
    case "No"
        clearData()
end

Instead use:

switch reply
    case "Yes"
        saveData()
    case "No"
        clearData()
    otherwise
        % Should not get here.
        error("Unknown reply " + reply)
end

Mixed types in expressions cc4m_logo_inline

IDSTAT-7
TitleDo not use multiple operand types per operator.
PriorityStrongly recommended
Severity level5
DescriptionDo not use multiple operand types per operator. For example, do not mix logical and numerical operatonds with a multiplication operator.
RationaleMixing operand types per operator can cause unexpected results and may lead to errors in case of true incompatibilities.

Avoid:

d = a * b && c;

Instead use:

d = (a * b > 0) && c;

Parentheses in logical expressions cc4m_logo_inline

IDSTAT-8
TitleUse parentheses to clarify precedence in logical expressions.
PriorityStrongly recommended
Severity level10
DescriptionUse parentheses to clarify the precedence of operands in expressions with multiple logical operators. No parentheses are required when only one type of logical operator is used. For example: d = a && b && c;.
RationaleBy clarifying the precedence of the operands in such expressions, readability is improved and unexpected behaviour is prevented.

Avoid:

d = a && b || c;

Instead use:

d = (a && b) || c;

Parentheses in mathematical expressions cc4m_logo_inline

IDSTAT-9
TitleUse parentheses to clarify precedence in mathematical expressions.
PriorityStrongly recommended
Severity level10
DescriptionUse parentheses to clarify the precedence of operands in expressions with multiple mathematical operators. No parentheses are required when only one type of mathematical operator is used. For example: d = a * b * c;.
RationaleBy clarifying the precedence of the operands in such expressions, readability is improved and unexpected behaviour is prevented.

Avoid:

d = a * b + c;
h = f / 2 * g;

Instead use:

d = (a * b) + c;
h = (f / 2) * g;

Assert inputs cc4m_logo_inline

IDSTAT-10
TitleEvery assert call shall have an error ID and a message as 2nd and 3rd inputs.
PriorityMandatory
Severity level6
DescriptionEvery call to the built-in assert function shall have an error identifier and a message as second and third inputs.
RationaleIncluding an identifier allows for better testing and exception handling. Including a proper error message directly clarifies the problem.

Avoid:

assert(~isempty(list))

Instead use:

assert(~isempty(list), 'ClassName:MethodName:ListIsEmpty', 'The list shall not be empty.')

Global variables cc4m_logo_inline

IDSTAT-11
TitleDo not use global variables.
PriorityMandatory
Severity level4
DescriptionThe global keyword should not be used.
RationaleThe value of global variables can change from anywhere, which can make things unnecessarily complicated.

Constant conditional statements cc4m_logo_inline

IDSTAT-12
TitleDo not use conditions like if true and similar.
PriorityStrongly recommended
Severity level5
DescriptionDo not use conditions that are always true or always false such as if true or elseif 0. MATLAB's Code Analyzer warns about some of these cases.
RationaleThese constructs may cause unreachable code or unintended behaviour.

Avoid:

if x > 0 || true
    disp(x)
end   

Instead use:

disp(x)

Group struct field definitions cc4m_logo_inline

IDSTAT-13
TitleAll fields of a struct shall be defined in a single, contiguous block of code.
PriorityStrongly recommended
Severity level6 when the code is meant for code generation, otherwise 10
DescriptionNo fields shall be added to a struct after using it.
RationaleLines of code or functions using the struct might assume that all fields are already there, resulting in an error if the field is not there.

Avoid:

s = struct("f", 2, "g", 3);

computeCost(s);
s.h = 'new field';

Instead use:

s = struct("f", 2, "g", 3, "h", 'new field');

computeCost(s);

Eval-functions cc4m_logo_inline

IDSTAT-14
TitleDo not use the built-in eval. Minimize the use of feval, evalin and evalc.
PriorityStrongly recommended
Severity level5
DescriptionDo not use the built-in eval. Minimize the use of feval, evalin and evalc.
RationaleThese functions can have harmful results and statements using them are usually difficult to read and maintain.
Additionally, it may be overlooked when variables are defined or altered by calls to these functions.

Keywords break, continue and return cc4m_logo_inline

IDSTAT-15
TitleCarefully use break, continue and return.
PriorityMandatory
Severity level10
DescriptionCarefully use the keywords break, continue and return .
RationaleUsing break, continue or return decreases readability because the end of the function is not always reached. By avoiding these keywords, the flow of the code remains clear. However, these keywords can be useful to reduce complexity and improve performance.

Avoid:

if isempty(x)
    return
end

<rest of the code>

Instead use:

if isempty(x)
    % No further actions.
else
    <rest of the code>
end

Shell escape cc4m_logo_inline

IDSTAT-16
TitleDo not use the shell escape function.
PriorityMandatory
Severity level6
DescriptionDo not use the shell escape function. If necessary, use the system function instead.
RationaleWhen using the !program_to_execute syntax to execute external programs, no dynamic input or program names can be used.
ExceptionApplication development.

Avoid:

!mycommand

Instead use:

system('mycommand')

Dependencies are known cc4m_logo_inline

IDSTAT-17
TitleMake sure all functions called are known.
PriorityMandatory
Severity level3
DescriptionMake sure all functions called are known.
RationaleAttempting to access packages, classes and functions not on the MATLAB path will result in an error.

Try for exception handling cc4m_logo_inline

IDSTAT-18
TitleOnly use the try construct for exception handling.
PriorityStrongly recommended
Severity level5
DescriptionOnly use the try construct for exception handling.
An exception object must be assigned or created and an error function must be called in the catch.
Do not use try/catch to suppress errors or to express simple conditions.
There are other, more suitable options for that.
RationaleUsing try for simple error suppression can result in poor performance and unexpected behaviour. When a different error occurs than the one expected, it can go undetected because of the try/catch.

Avoid:

try
    nElems = container.nElements;
catch
    nElems = 0;
end

Instead use:

if isfield(container, 'nElements')
    nElems = container.nElements;
else
    nElems = 0;
end

Floating-point comparisons cc4m_logo_inline

IDSTAT-19
TitleDo not compare floating-point values using == or ~=.
PriorityStrongly recommended
Severity level3
DescriptionDo not compare floating-point values using == or ~=. Use a tolerance instead.
RationaleRounding errors due to algorithm design or machine precision can cause unexpected inequalities.

Avoid:

out = myFcn(in) == sqrt(3);

Instead use:

out = abs(myFcn(in) - sqrt(3)) < 1e-12;

Workspace variable ans cc4m_logo_inline

IDSTAT-21
TitleDo not use the workspace variable ans.
PriorityRecommended
Severity level6
DescriptionTo keep things clean, do not use the workspace variable ans.
RationaleUse of the workspace variable ans reduces the robustness and security of the code.

Debugging functions cc4m_logo_inline

IDSTAT-22
TitleDo not use debugging functions that interact with the MATLAB debugger.
PriorityRecommended
Severity level6
DescriptionDo not use debugging functions such as dbstep, dbcont, dbquit, keyboard or other functions that interact with the MATLAB debugger.
RationaleThese functions that interact with the MATLAB debugger reduce the robustness of the code.

Logical indexing

IDSTAT-24
TitleUse logical indexing instead of linear or subscript indexing where possible.
PriorityStrongly recommended
Severity level6
DescriptionTo speed up your code, use logical indexing instead of linear or subscript indexing where possible.
RationaleLogical indexing is faster and more readable.

Avoid:

index = intersect(find(v > MIN), find(v < MAX));

Instead use:

index = (v > MIN) & (v < MAX);

Loop vectorization

IDSTAT-25
TitleVectorize loops where feasible.
PriorityStrongly recommended
Severity level10
DescriptionInstead of looping over the elements of arrays, apply operations to them in their entirety.
RationaleVectorized loops are faster, more robust, more readable, and more maintainable.

Avoid:

dataResult = false(size(dataset));

for iElem = 1 : numel(dataset)
    if dataset(iElem) < limit(iElem)
        dataResult(iElem) = true;
    else
        dataResult(iElem) = false;
    end
end

Instead use:

dataResult = dataset < limit;

Zero before decimal point

IDSTAT-26
TitleAlways use a zero before the decimal point in numeric expressions.
PriorityRecommended
Severity level10
DescriptionAlways use a zero before the decimal point in numeric expressions.
RationaleIncreases the readability of the code.

Avoid:

THRESHOLD = .5;

Instead use:

THRESHOLD = 0.5;

Accessing other workspaces cc4m_logo_inline

IDSTAT-27
TitleAvoid using functions that access or depend on workspaces outside the scope of the current function.
PriorityStrongly recommended
Severity level6
DescriptionDo not use functions accessing workspaces outside the scope of the current function such as assignin, evalin, clc.
RationaleThese functions reduce the portability, robustness and readability of the code.
ExceptionApplication development and Simulink tools.

Use switch blocks

IDSTAT-28
TitleUse a switch block instead of many if-elseif-else statements.
PriorityRecommended
Severity level5
DescriptionUse a switch block instead of many if-elseif-else statements when possible.
RationaleThe notation of a switch block is more concise and therefore, more readable and easier to maintain.

Avoid:

if name == "Bill"
    ...
elseif ismember(name, ["Judith", "Bob"])
    ...
elseif name == "Steve"
    ...
else
    ...
end

Instead use:

switch name
    case "Bill"
        ...
    case {"Judith", "Bob"}
        ...
    case "Steve"
        ...
    otherwise
        ...
end

Variable in one unit

IDSTAT-29
TitleUse a variable in one unit as much as possible.
PriorityStrongly recommended
Severity level10
DescriptionUse a variable in one unit as much as possible. Use a named constant for converting to another unit if conversion is truly necessary.
RationaleMaintain readability by using the same unit of measure throughout a function.

Avoid:

halfLifeTime = 580; % [s]
halfLifeTime = halfLifeTime / 3600; % [h]

Instead use:

SECONDS_TO_HOURS    = 1 / 3600;
halfLifeTime        = 580; % [s]
halfLifeTime        = halfLifeTime * SECONDS_TO_HOURS; % [h]

Higher level guidelines

The guidelines in this chapter transcend individual statements. These higher-level guidelines treat things like code complexity and function types.

Complexity cc4m_logo_inline

IDFCNS-1
TitleKeep functions short and simple.
PriorityStrongly recommended
Severity level4
DescriptionKeep number of lines of code and cyclomatic complexity to an acceptable level, especially for nested functions and methods in a classdef file. Use the values of the table below.
RationaleShort functions are more likely to be readable, reusable and testable.



Function typeMaximum cyclomatic complexityMaximum number of lines of code
Main20100
Local (Sub)1550
Methods in a classdef1020
Nested510

Number of function arguments cc4m_logo_inline

IDFCNS-2
TitleLimit the number of inputs and outputs of a function.
PriorityRecommended
Severity level10
DescriptionLimit the number of inputs and outputs of a function to five. If necessary, combine multiple arguments into a struct.
RationaleThis helps prevent a long calling syntax, which in turn improves the readability and reusability of the code.

Avoid:

out = computeWeight(blockHeight, blockWidth, blockDepth, density, nBlocks, idx);

Instead use:

out = computeWeight(blockData, nBlocks, idx);

Constructors with single output cc4m_logo_inline

IDFCNS-3
TitleEvery constructor shall have exactly one output.
PriorityMandatory
Severity level5
DescriptionEvery constructor shall have exactly one output: an object of the class.
RationaleA second constructor output is unusual, so will be unexpected for readers of the code.

Avoid:

classdef Computer
    methods
        function [obj, out2] = Computer(in)
            obj.value = in;
            out2 = 2 * in;
        end
    end
end

Instead use:

classdef Computer
    methods
        function obj = Computer(in)
            obj.value = in;
        end
    end
end

Scripts cc4m_logo_inline

IDFCNS-4
TitleDo not use scripts. Use functions instead.
PriorityRecommended
Severity level5
DescriptionUse functions even if there are no inputs or outputs.
RationaleThe scope of variables in a script is not bounded as one might expect. It is therefore safer to use functions instead. Additionally, scripts are not compatible with Matlab Coder.
ExceptionInitialization of a project, or specifically creating base workspace structures that are used in models, without the need for assignin.

Editor warnings cc4m_logo_inline

IDFCNS-5
TitlePrevent or suppress Code Analyzer messages.
PriorityStrongly recommended
Severity level5
DescriptionPrevent or suppress Code Analyzer messages shown in the MATLAB editor.
When the messages cannot be prevented, suppress them on an individual basis and add the reason in the comments.
RationaleThe messages usually indicate that improvements can be made to the performance or stability of the code.
Adding file-wide Code Analyzer suppressions is discouraged because new triggers of the messages may be overlooked.

Avoid:

%#ok<*ABCDE> Suppress a Code Analyzer warning in the entire file.

Instead use:

%#ok<ABCDE> Suppress the Code Analyzer warning on this line alone.

Getters and setters cc4m_logo_inline

IDFCNS-6
TitleMinimize the use of Getters and Setters.
PriorityStrongly recommended
Severity level5
DescriptionDo not write methods using the get.<property> and set.<property> syntax. Write explicit methods for getting or setting property values if necessary.
RationaleProperty getters and setters can cause unexpected behaviour because code is run unexpectedly when the property's value is changed or requested.

Mex-files cc4m_logo_inline

IDFCNS-7
TitleWhen using a mex-function in your code, make sure versions of the file are available for all platforms.
PriorityMandatory
Severity level3
DescriptionWhen using a mex-function in your code, make sure versions of the file are available for Windows (32 and 64 bit), MacOS and Unix.
RationaleThis increases the chance your code will run successfully on other platforms as well.

Nesting depth cc4m_logo_inline

IDFCNS-8
TitleLimit nesting depth to a maximum of five.
PriorityStrongly recommended
Severity level5
DescriptionDo not nest blocks of code deeper than five levels. If necessary, refactor into multiple functions.
RationaleDeeply nested code is often less readable and it can be a sign of inefficient code.

Repeated code

IDFCNS-9
TitleDo not use the same block of more than once in a function/in multiple functions.
PriorityStrongly recommended
Severity level6
DescriptionIf a function contains a block of code that is repeated more than one time, refactor it into a single function.
RationaleRefactoring of repeated blocks of code into single functions increases the maintainability, readability and reusability of the code.

Ownership structure

IDFCNS-10
TitleOwnership of a structure resides with the creator of that structure.
PriorityStrongly recommended
Severity level6
DescriptionOwnership of a structure resides with the creator of that structure, so do not add or remove fields from an existing structure outside of the function in which it was created.
RationaleAdding or removing fields from an existing structure outside of the function in which it was created reduces the robustness of the code. Related to coder compatibility, in generated code, adding a new field to a structure that has already been read or indexed will cause an error.

Avoid:

function [out] = calculateSpeed(car)

out = car;

% do not remove fields from existing struct
car = rmfield(car, 'speed');

Instead use:

function [out] = calculateSpeed(car)

out = car;

% clear the field
car.speed = [];

Single responsibility

IDFCNS-11
TitleFunctions should do precisely one thing well, and encapsulate a single idea.
PriorityRecommended
Severity level6
DescriptionSingle responsibility principle : all sub-functions and most functions should do one thing very well, and encapsulate a single idea.
RationaleThe single responsibility principle makes code more readable, modular, and testable. Multi-purpose functions can often be split up into atomic units which are called on the input data in sequence. Functions should not try to be all things to all users.

Commented out code

IDFCNS-12
TitleRemove commented out code.
PriorityStrongly recommended
Severity level8
DescriptionRemove commented-out lines of code.
RationaleRemoving commented-out code increases readability and it prevents someone from unintentionally enabling it again.

Reuse of iterator variables

IDFCNS-13
TitleDo not reuse iterator variables within a function.
PriorityStrongly recommended
Severity level6
DescriptionDo not reuse iterator variables within the same function. Limit the scope of an iterator variable to its for-loop.
RationalePrevents renaming all iterators when only the one for a specific loop must be renamed. Also improves readability.

Avoid:

for iNode = 1 : numel(nodes)
    ...
end

for iNode = 1 : 2 : 11
    ...
end

Instead use:

for iNode = 1 : numel(nodes)
    ...
end

for iValue = 1 : 2 : 11
    ...
end

Rewriting existing functions

IDFCNS-14
TitleWhen rewriting existing functions, do not make a new copy of them with slightly modified code.
PriorityRecommended
Severity level5
DescriptionDo not copy-paste an existing function as a local function of your code. Instead, use a wrapper around existing functionality.
RationaleMultiple forks, duplications and reinventions of the wheel make a code base less modular and less maintainable.

Columns with implicit meaning

IDFCNS-15
TitleAvoid the use of matrices in which rows or columns have implicit meaning.
PriorityRecommended
Severity level5
DescriptionAvoid the use of matrices in which rows or columns have implicit meaning. Use individual vectors instead.
RationaleUsing matrices with implicit row or column meanings reduces the readability and robustness of the code.

Avoid:

distance = sqrt(coordinates(:, 1) .^ 2 + coordinates(:, 2) .^ 2);

Instead use:

distance = sqrt(x .^ 2 + y .^ 2);

Nested functions cc4m_logo_inline

IDFCNS-16
TitleUse nested functions sparingly/only when really beneficial.
PriorityStrongly recommended
Severity level5
DescriptionUse nested functions sparingly/only when really beneficial.
RationaleNested functions reduce the readability and robustness of the code and can not be tested independently.
ExceptionBecause variables can be shared, nested forms can be useful to prevent a massive interface with a lot of inputs and outputs.

Input parameter dependency

IDFCNS-17
TitleFunction input arguments must be independent.
PriorityRecommended
Severity level6
DescriptionFunction input arguments must be independent, and the function must not assume a dependency between them.
RationaleAssuming a dependency between independent input parameters reduces the robustness of the code. Conversely, if the inputs to a function are dependent, treating them as independent also reduces robustness.

Avoid:

function [meanV, meanA] = getMeanVandA(velocities, distances, timePts)
meanV = sum(distances) ./ sum(timePts);
meanA = velocities(end) ./ sum(timePts);
end

function vectorOut = processVector(vectorIn, vectorLength)
for iIdx = 1 : vectorLength
    vectorOut(ii) = processScalar(vectorIn(ii));
end
end

Instead use:

function [meanV, meanA] = getMeanVandA(distances, timePts)
meanV      = sum(distances) ./ sum(timePts);
velocities = distances ./ timePts;
meanA      = velocities(end) ./ sum(timePts);
end

function vectorOut = processVector(vectorIn)
for iIdx = 1 : length(vectorIn)
    vectorOut(ii) = processScalar(vectorIn(ii));
end
end