Skip to content
Arthur Benemann edited this page Mar 15, 2013 · 1 revision

In order to make the source code easier to read and maintain, we have established a number of conventions applying to its format and content. In addition to the specific points covered below, the code and supporting documentation should aim to be descriptive and explanatory, and it should try to be no more complex than necessary to get the job done well.

This reference is a work in progress, feedback and suggestions are welcome.

General Principles

Where possible, keep the code simple and straightforward. As this is an Arduino-based project, look to the level and style of code that the Arduino community generally uses and understands to establish a baseline.

When considering the use of a more sophisticated technique or language feature, consider whether it will improve the overall comprehensibility of the code, or whether a slightly more verbose but simpler implementation will achieve the same end with reduced confusion.

Use libraries and classes as ways to hide complexity; it is generally more acceptable to provide a class with a simple and easy to understand interface that internally uses more complex techniques than it is to implement those techniques directly.

Document your code. Everything that the code does should be explained in a comment; for any operation the code performs, a reader should be able to answer "what is this doing?" and "why is it doing it?" by reading the comments. Take advantage of the naming rules detailed below to help explain what the code does.

Names

In general, we prefer expressive identifier names using whole words separated by underscores. Try to keep names to a reasonable length (less than 30 characters or so). When possible, use standard terms and acronyms. Acronyms should be capitalised correctly, even in identifiers that are described as being lowercase.

When constructing an identifier name, order words starting with the more general and progressing to the more specific.

roll_command
GPS_update_rate
File names

Source code filenames should begin with a capital letter, other filenames should not unless required by another convention. The main file in a sketch should be named using !CamelCase in order to distinguish it (and in accordance with convention).

ArduPilotMega.pde Math.cpp eeprom.txt
Type names

Structure, class, enumeration and typedef'ed names should begin with a capital letter. When these types are provided by a library, they may be prefixed by the library name.

Library class names should begin with {{{AP_}}} if they are specific to the !ArduPilot project, otherwise they should try to conform to Arduino norms.

class Vector; class AP_GPS_Auto; typedef unsigned long Latitude;
Function names

Function names should be all lowercase. Class member function names do not need to begin with or include the class name, as it is implied. Functions marked static in a file may omit mention of the file's purpose if their use is otherwise obvious. Private member function names should begin with an undercore, protected member function names should not.

int radio_get_switch_setting(void); static bool is_complete(void); class GPS { public: void init(void); protected: int status(void); private: bool _read(void); };
Global variable names

Global variable names should be all lowercase, and prefixed with {{{g_}}}.

unsigned long g_startup_time;
Global constant names

Global constant names should be all lowercase, and prefixed with {{{k_}}}. All constants should be marked with the {{{const}}} qualifier.

Enumeration members should be named like constants.

const float k_pi = 3.1415; enum Status { k_operational, k_defunct };
Local variable names

Local variable names should be all lowercase. Single-letter identifier names are acceptable for common uses; e.g. {{{i, j, k}}} for nested loop counters, {{{c}}} for a character, {{{s, p}}} for pointers to character strings.

Member variable names

Private member variable names should begin with an underscore. Protected and public member variable names should not.

class Foo { public: int x; protected: int y; private: int _z; };

Functions

Where possible, group functions into classes. When functions are exported by a library, if the library does not implement a class its functions should be grouped into a namespace.

In general, avoid global functions when a better alternative is available. If a global function is only used and appropriate in a single file, it should be marked static. Class member functions should be private or protected unless they form a part of the class' contract with its clients.

Classes

Avoid the use of public member variables for class properties; implement get/set methods instead. Where a class has a property {{{int some_property}}}, implement

int	get_some_property(void);
void	set_some_property(int new_value);

If a class has only one property and exists primarily for the purpose of that property, it is acceptable to have methods {{{get}}} and {{{set}}} omitting the property name. Consider overloading {{{operator &}}} in the case where the class masquerades as a variable.

Constants

Where possible use global constants rather than preprocessor definitions. i.e. instead of

#define FROG_SCALING_FACTOR	4.3

use

const float k_frog_scaling_factor = 4.3

For class-specific constants, use {{{static const}}} members or enumerations as appropriate.

Formatting

  • Code should be formatted according to the style known as 1TBS. Experience has shown that it produces code that is easy to read and harder to get "wrong". It's also easy to configure most text editors to help you keep code in this style.
  • Source line lengths should be no more than 120 characters (barring explicit technical constraints).
  • Line endings should be native to the platform on which the file was checked out, and all files containing text should have the appropriate SVN attributes to ensure that line endings are translated correctly.
  • The default indentation will be four spaces.
  • No tab characters in our source files. This means the code will always look 'right' in any editor.

editor configuration examples TBD

See the Tools section below for recommended tools to aid in formatting your code.

Other Code Conventions

We should prefer the use of a .h/.cpp file pair when adding new functionality to a sketch, rather than adding another .pde file. The compiler considers each .cpp file separately, but the .pde files are smushed together before the compiler gets to see them. Thus, things that the programmer believes are separate because they're in separate files are in fact not separate.

This also requires the programmer to create a corresponding .h file which contains explicit declarations of everything inside the file that is intended for use by other files. This provides a place for documentation for those interfaces, as well as making it explicitly clear to anyone else coming along later what the expected interface to the contents of the file are.

Avoid the use of C source files, as the compiler treats them in subtly different ways that will not be obvious to many developers.

Useful Tools

The Artistic Style source code formatter can be used to help keep code in a consistent style. The following configuration file can be used with the command-line version of Artistic Style.

There is a Windows GUI available as well. The Universal Indent GUI also supports Artistic Style and can read the configuration file, but on at least some platforms Artistic Style support is broken in the most recent version.

#
# Artistic Style configuration file for the ArduPilot Coding Conventions
#       http://code.google.com/p/ardupilot-mega/wiki/Naming
#
style=1tbs                 # http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS
indent-preprocessor        # multi-line preprocessor macros will be indented
min-conditional-indent=0   # multi-line conditional expressions are indented to follow their parentheses.
pad-oper                   # spaces are added around arithmetic operators
pad-header                 # spaces are added between if/while/for/switch and their arguments
unpad-paren                # spaces are removed from around parentheses in expressions
keep-one-line-statements   # don't wrap complex or multi-line statements
align-pointer=name         # keep the * in pointer declarations with the pointer name
Clone this wiki locally