ICub Coding Guidelines

From Wiki for iCub and Friends
Revision as of 11:38, 23 August 2009 by Dvernon (talk | contribs) (→‎C Language Conventions)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The correct title of this article is iCub Coding Guidelines. The initial letter is shown capitalized due to technical restrictions.

Programming Style

Declarations

Number Per Line

One declaration per line is recommended since it encourages commenting:

  int level; // indentation level
  int size;  // size of table

is preferable to:

  int level, size;

Do not put different types on the same line:

  int foo, fooarray[]; //WRONG!

Initialization

Initialize local variables where they are declared. The only reason not to initialize a variable where it's declared is if the initial value depends on some computation occurring first.

Placement

Put declarations only at the beginning of blocks. A block is any code surrounded by curly braces { and }. Don't wait to declare variables until their first use. Ideally, declare all variables at the beginning of the method or function block.

  void myMethod() {
     int int1 = 0; // beginning of method block
 
     if (condition) {
        int int2 = 0; // beginning of "if" block
        ...
     }
  }


Class Declarations

The following formatting rules should be followed:

  • No space between a method name and the parenthesis ( starting its parameter list.
  • The open brace { appears at the end of the same line as the declaration statement.
  • The closing brace } starts a line by itself indented to match its corresponding opening statement.

    class Sample {
         ...
    }  

  • Methods are separated by a blank line.

Statements

Simple Statements

Each line should contain at most one statement. For example:

  argv++;         // Correct
  argc++;         // Correct
  argv++; argc--; // AVOID!

Compound Statements

Compound statements are statements that contain lists of statements enclosed in braces { statements }. See the following sections for examples.

  • The enclosed statements should be indented one more level than the compound statement.
  • The opening brace should be at the end of the line that begins the compound statement; the closing brace should begin a line and be indented to the beginning of the compound statement.
  • Braces are used around all statements, even single statements, when they are part of a control structure, such as a if-else or for statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.

    if (condition) {
       a = b;
    }
    else {
       a = c;
    }

return Statements

A return statement with a value should not use parentheses unless they make the return value more obvious in some way. For example:

  return;

  return myDisk.size();

  return TRUE;

if, if-else, if else-if else Statements

The if-else class of statements should have the following form:

  if (condition) {
     statements;
  }

  if (condition) {
     statements;
  } else {
     statements;
  }

  if (condition) {
     statements;
  } else if (condition) {
     statements;
  } else {
     statements;
  }

Always use braces { }, with if statements. Don't use

  if (condition) //AVOID!  
     statement;

for Statements

A for statement should have the following form:

  for (initialization; condition; update) {
     statements;
  }

while Statements

A while statement should have the following form:

  while (condition) {
     statements;
  } 

do-while Statements

A do-while statement should have the following form:

  do {
     statements;
  } while (condition); 

switch Statements

A switch statement should have the following form:

  switch (condition) {
  case ABC:
     statements;
     /* falls through */
  case DEF:
     statements;
     break;
  case XYZ:
     statements;
     break;
  default:
     statements;
     break;
  }

Every time a case falls through (i.e. when it doesn't include a break statement), add a comment where the break statement would normally be. This is shown in the preceding code example with the /* falls through */ comment.


Every switch statement should include a default case. The break in the default case is redundant, but it prevents a fall-through error if later another case is added.

Naming Conventions

C vs. C++

Naming conventions make programs more understandable by making them easier to read. Since iCub software uses both the C language and the C++ language, sometimes using the imperative programming and object-oriented programming paradigms separately, sometimes using them together, we will adopt two different naming conventions, one for C and the other for C++. The naming conventions for C++ are derived from the JavaDoc standards.

C++ Language Conventions

The following are the naming conventions for identifiers when using C++ and the object-oriented paradigm.


Identifier Type   Rules for Naming                                    Examples  
                         
Classes           Class names should be nouns, in mixed case with     class ImageDisplay                 
                  the first letter of each internal word capitalized  class MotorController              
                                                                                                                
Methods           Method names should be verbs, in mixed case with    int grabImage()                    
                  the first letter in lowercase, with the first       int setVelocity()                  
                  letter of each internal word capitalized                                                      
                                                                                                                
Variables         variable names should be in mixed case with the     int    i;                 
                  first letter in lowercase, with the first letter    float  f;                 
                  of each internal word capitalized                   double pixelValue;        
                                                                                                                
Constants         The names of variables declared as constants        const int WIDTH = 4;      
                  should be all uppercase with words separated by                                               
                  underscores _                                                                 
                                                                                                                
Type Names        Typedef names should use the same naming policy as  typedef uint16 ModuleType 
                  that used for class names                                                                     
                                                                                                               
Enum Names        Enum names should use the same naming policy as     enum PinState {           
                  that used for class names.                             PIN_OFF,               
                  Enum labels should should be all uppercase with        PIN_ON                 
                  words separated by underscores _                    };            

C Language Conventions

The following are the naming conventions for identifiers when using C.

Identifier Type   Rules for Naming                                    Examples  
 
Functions         Function names should be all lowercase with words   int  display_image()      
                  separated by underscores _                          void set_motor_control()  
                                                                                                            
Variables         variable names should be all lowercase with words   int    i;                 
                  separated by underscores _                          float  f;                 
                  of each internal word capitalized                   double pixel_value;       
                                                                                                            
Constants         Constants should be all uppercase with words        #define WIDTH 4           
                  separated by underscores _                                                  
                                                                                                            
#define           #define and macro names should all uppercase        #define SUB(a,b) ( (a) - (b) )    
and Macros        with words separated by underscores _

And Finally: Where To Put The Opening Brace {

There are two main conventions on where to put the opening brace of a block. In this document, we have adopted the JavaDoc convention and put the brace on the same line as the statement preceding the block. For example:

  class Sample {  
     ...
  }
 

  while (condition) {
     statements;
  } 

The second convention is to place the brace on the line below the statement preceding the block and it indent it to the same level. For example:

  class Sample 
  {  
     ...
  }


  while (condition) 
  {
     statements;
  } 

If you really hate the JavaDoc format, use the second format, but be consistent and stick to it throughout your code.

Programming Practice

C++ Language Conventions

Access to Data Members

Don't make any class data member public without good reason.


One example of appropriate public data member is the case where the class is essentially a data structure, with no behaviour. In other words, if you would have used a struct instead of a class, then it's appropriate to make the class's data members public.


C Language Conventions

Use the Standard C syntax for function definitions:

  void example_function (int an_integer, long a_long, short a_short)
  ...

If the arguments don't fit on one line, split the line according to the rules in above.

  void example_function (int an_integer, long a_long, short a_short,
                         float a_float, double a_double)
  ...

General Issues

Conditional Compilation

Avoid the use of conditional compilation. If your code deals with different configuration options, use a conventional if-else construct. If the code associated with either clause is long, put it in a separate function. For example, please write:

  if (HAS_FOO) {
     ...
  }
  else {
     ...
  } 

instead of:

  #ifdef HAS_FOO
     ...
  #else
     ...
  #endif

Writing Robust Programs

Avoid arbitrary limits on the size or length of any data structure, including arrays, by allocating all data structures dynamically. Use malloc or new to create data-structures of the appropriate size. Remember to avoid memory leakage by always using free and delete to deallocate dynamically-created data-structures.


Check every call to malloc or new to see if it returned NULL.


You must expect free to alter the contents of the block that was freed. Never access a data structure after it has been freed.


If malloc fails in a non-interactive program, make that a fatal error. In an interactive program, it is better to abort the current command and return to the command reader loop.


When static storage is to be written during program execution, use explicit C or C++ code to initialize it. Reserve C initialize declarations for data that will not be changed. Consider the following two examples.

  static int two = 2; // two will never alter its value
  ...
  static int flag;
  flag = TRUE;        // might also be FALSE

Constants

Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values.

Variable Assignments

Avoid assigning several variables to the same value in a single statement. It is hard to read.


Do not use the assignment operator in a place where it can be easily confused with the equality operator.

  if (c++ = d++) { // AVOID!  
     ...
  }

should be written as

  if ((c++ = d++) != 0) {
     ...
  }

Do not use embedded assignments in an attempt to improve run-time performance. This is the job of the compiler.

  d = (a = b + c) + r; // AVOID!

should be written as

  a = b + c;
  d = a + r;

Parentheses

Use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others --- you shouldn't assume that other programmers know precedence as well as you do.

if (a == b && c == d) // AVOID!

if ((a == b) && (c == d)) // USE

Standards for Graphical Interfaces

When you write a program that provides a graphical user interface (GUI), you should use a cross-platform library. At the very least, it must possible to compile your GUI code for both a Window environment and a Linux environment.

Error Messages

Error messages should look like this:

  function_name: error message


License Messages

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

<Program name and version>
 
Copyright (C) <year> <name of author>, <author institute>
RobotCub Consortium, European Commission FP6 Project IST-004370
email:   <firstname.secondname>@robotcub.org
website: www.robotcub.org

This program comes with ABSOLUTELY NO WARRANTY.
Permission is granted to copy, distribute, and/or modify this program 
under the terms of the GNU General Public License, version 2 
or any later version published by the Free Software Foundation; 
see http://www.robotcub.org/icub/license/gpl.txt