Style Guide for MATLAB Code

From miffyliye.org
Jump to: navigation, search

Introduction

This document gives coding conventions for the MATLAB code comprising the standard library in the main MATLAB distribution.

This document was adapted from PEP 8, which was adapted from Guido's original Python Style Guide essay, with some additions from Barry's style guide.

Some styles were adopted from the MathWorks, Inc.

A Foolish Consistency is the Hobgoblin of Little Minds

One of Guido's key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As PEP 20 says, "Readability counts".

A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.

But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgement. Look at other examples and decide what looks best. And don't hesitate to ask!

Two good reasons to break a particular rule:

  1. When applying the rule would make the code less readable, even for someone who is used to reading code that follows the rules.
  2. To be consistent with surrounding code that also breaks it (maybe for historic reasons) -- although this is also an opportunity to clean up someone else's mess.

Code Lay-Out

Indentation

Use 4 spaces per indentation level.

Continuation lines should align wrapped elements vertically using a hanging indent. When using a hanging indent the following considerations should be applied: there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line.

Yes:

% Aligned with opening delimiter
foo = long_function_name(var_one, var_two, ...
                         var_three, var_four);

% More indentation included to distinguish this from the rest.
function foo = long_function_name( ...
        var_one, var_two, var_three, ...
        var_four)
    disp(var_one);
end

No:

% Arguments on first line forbidden when not using vertical alignment
foo = long_function_name(var_one, var_two, ...
    var_three, var_four);

% Further indentation required as indentation is not distinguishable
function foo = long_function_name(
    var_one, var_two, var_three, ...
    var_four)
    disp(var_one);
end

Optional:

% Extra indentation is not necessary.
foo = long_function_name( ...
  var_one, var_two, ...
  var_three, var_four);

Tabs or Spaces?

Never mix tabs and spaces.

One popular way of indenting MATLAB is with spaces only. The other popular way is with tabs only. Code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.

For new projects, spaces-only are strongly recommended over tabs. Most editors have features that make this easy to do.

Maximum Line Length

Limiting all lines to a maximum of 79 characters is recommended.

Limiting windows to 80 characters makes it possible to have several windows side-by-side. The default wrapping on such devices disrupts the visual structure of the code, making it more difficult to understand. Therefore, please limit all lines to a maximum of 79 characters.

For flowing long blocks of text (docstrings or comments), limiting the length to 72 characters is recommended.

Make sure to indent the continued line appropriately. The preferred place to break around a binary operator is after the operator, not before it. Some examples:

function foo = num2line_style(var_matrix)
    if isempty(var_matrix)
        foo={};
        return;
    end

    style_set = {'-', '--', '-.', ':'};
    style_range = length(style_set);
    [rows, columns] = size(var_matrix);
    if max(rows, columns) == 1
        foo=style_set(mod(var_matrix - 1, style_range) + 1);
    elseif rows > 1
        foo = cell(rows, columns);
        for row_index = 1:rows
            foo(row_index,:) = ...
                num2line_style( ...
                    mod(var_matrix(row_index,:) - 1, style_range) + 1);
        end
    elseif columns > 1
        foo = cell(1, columns);
        for column_index = 1:columns
            foo(column_index) = ...
                num2line_style( ...
                    mod(var_matrix(column_index) - 1, style_range) + 1);
        end
    else
        foo = style_set(mod(var_matrix - 1, style_range) + 1);
    end
end

Blank Lines

Separate top-level function and class definitions with two blank lines.

Method definitions inside a class are separated by a single blank line.

Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).

Use blank lines in functions, sparingly, to indicate logical sections.

Encodings

The ASCII encoding is the default choice. When using ASCII, the code should contain only the ASCII printable characters.

UTF-8 is preferred over ASCII and Latin-1 encoding, if the code contains characters beyond the ASCII printable characters.

It is recommended that string literals and comments also be in ASCII. The only exceptions are (a) test cases testing the non-ASCII features, and (b) names of authors. Authors whose names are not based on the latin alphabet must provide a latin transliteration of their names.

Toolboxes and Imports

  • Toolboxes used should be specified in the comment at top of the file.
  • Imports should usually be on separate lines, e.g.:
Yes: import package_name.class_name
     import package_name.function_name

No:  import package_name.class_name package_name.function_name
  • Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.
Imports should be grouped in the following order:
  1. standard library imports
  2. related third party imports
  3. local application/library specific imports

Whitespace in Expressions and Statements

Pet Hates

Avoid extraneous whitespace in the following situations:

  • Immediately inside parentheses, brackets or braces.
Yes: foo = {ham(1), {eggs}};
No:  foo = { ham( 1 ), { eggs } };
  • Immediately before a comma, semicolon, or colon:
Yes: foo = [1, 2, 3; 4:6];
No:  foo = [1 , 2 , 3 ; 4 : 6] ;
  • Immediately before the open parenthesis that starts the argument list of a function call
Yes: foo(1);
No:  foo (1);
  • Immediately before the open parenthesis that starts an indexing or slicing:
Yes: dict(1, :) = list(2);
No:  dict (1, :) = list (2);
  • More than one space around an assignment (or other) operator to align it with another.

Yes:

x = 1;
y = 2;
long_variable = 3;

No:

x             = 1;
y             = 2;
long_variable = 3;

Other Recommendations

  • Always surround these binary operators with a single space on either side: assignment (=), comparisons (==, <, >, !=, <>, <=, >=), Booleans (^, |, ~).
  • If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgement; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator.

Yes:

k = k + 1;
x = x*2 - 1;
hypot2 = x*x + y*y;
c = (a+b) * (a-b);

No:

k=k+1;
x = x * 2 - 1;
hypot2 = x * x + y * y;
c = (a + b) * (a - b);
  • Compound statements (multiple statements on the same line) are generally discouraged.

Yes:

do_one();
do_two();
do_three();

Rather not:

do_one(); do_two(); do_three();
  • While sometimes it's okay to put an if/for/while with a small body on the same line, never do this for multi-clause statements. Also avoid folding such long lines!

Rather not:

if foo == 'blah', do_blah_thing(); end
for x != lst, total = total + x; end
while t < 10, t = delay(); end

Definitely not:

if foo == 'blah', do_blah_thing();
else do_non_blah_thing(); end

try, something();
catch, cleanup(); end

do_one(); do_two(); do_three(long, argument,
                             list, like, this); end

if foo == 'blah', one(); two(); three(); end

Comments

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!

Comments should be complete sentences. If a comment is a phrase or sentence, its first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).

If a comment is short, the period at the end can be omitted. Block comments generally consist of one or more paragraphs built out of complete sentences, and each sentence should end in a period.

You should use two spaces after a sentence-ending period.

When writing English, The Oxford Guide to Style (for en-GB-oed) and The Elements of Style (for en-US) are recommended.

Python coders from non-English speaking countries: please write your comments in English, unless you are sure that the code will never be read by people who don't speak your language.

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.

Inline comments are unnecessary and in fact distracting if they state the obvious. Don't do this:

x = x + 1;                 % Increment x

But sometimes, this is useful:

x = x + 1;                 % Compensate for border

Documentation Strings

Conventions for writing good documentation strings (a.k.a. "docstrings") are written in Docstring Conventions.

  • Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you should have a comment that describes what the method does. This comment should appear after the definition line.

Naming Conventions

The naming conventions of MATLAB are a bit of a mess, so we'll never get this completely consistent -- nevertheless, here are the currently recommended naming standards. New modules and packages should be written to these standards, but where an existing library has a different style, internal consistency is preferred.

Descriptive: Naming Styles

There are a lot of different naming styles. It helps to be able to recognize what naming style is being used, independently from what they are used for.

The following naming styles are commonly distinguished:

  • b (single lowercase letter)
  • B (single uppercase letter)
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CamelCase
Note: When using abbreviations in CamelCase, capitalize all the letters of the abbreviation. Thus HTTPServerError is better than HttpServerError.
  • mixedCase (differs from CapitalizedWords by initial lowercase character!)
  • Capitalized_Words_With_Underscores (ugly!)

There's also the style of using a short unique prefix to group related names together. For example, the os.stat() function returns a tuple whose items traditionally have names like st_mode, st_size, st_mtime and so on. (This is done to emphasize the correspondence with the fields of the POSIX system call struct, which helps programmers familiar with that.)

In addition, the following special form using trailing underscores are recognized (this can generally be combined with any case convention):

  • single_trailing_underscore_: used by convention to avoid conflicts with MATLAB keyword

Prescriptive: Naming Conventions

Names to Avoid

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.

Using i and j as single character variable names is not recommended, because their default value is the imaginary unit in MATLAB, so that using them to represent other variables could be misleading.

Package and Module Names

Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. MATLAB packages should also have short, all-lowercase names, although the use of underscores is discouraged.

Since module names are mapped to file names, and some file systems are case insensitive and truncate long names, it is important that module names be chosen to be fairly short -- this won't be a problem on Unix, but it may be a problem when the code is transported to older Mac or Windows versions, or DOS.

Class Names

Almost without exception, class names use the CamelCase convention.

Global Variable Names

(Let's hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.

Function Names

Function names should be lowercase, with words separated by underscores as necessary to improve readability.

mixedCase is allowed only in contexts where that's already the prevailing style, to retain backwards compatibility.

Function and method arguments

Always use self for the first argument to instance methods.

Always use cls for the first argument to class methods.

If a function argument's name clashes with a reserved keyword, it is generally better to append a single trailing underscore rather than use an abbreviation or spelling corruption. Thus class_ is better than clss. (Perhaps better is to avoid such clashes by using a synonym.)

Method Names and Instance Variables

Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

Constants

Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW and TOTAL.

Programming Recommendations

  • Be careful when doing comparison operations.
  • Vectorize to improve performance.
  • Preallocating memory to improve performance.

References

Copyright

This document has been placed in the public domain.

See Also