Caret7:Development/CodingStandard

From Van Essen Lab

Revision as of 22:51, 7 September 2011 by Jschindl (Talk | contribs)
Jump to: navigation, search

Contents

Coding Standards

A reasonable coding standard will make code maintenance and development easier.

Most of these recommendations are from the Java Coding Conventions document that is reasonably short and clear.

Use an IDE!!!!

Be lazy (productive), use an IDE that will provide code completion, automatic indentation, etc. Make sure the IDE is setup to insert spaces and NOT tabs.

Naming

Use CamelCase naming as in the Java API. Caret has used this commonly implemented system since it was created. With CamelCase, each identifier is a series of words joined together without underscores or hyphens. In some cases, the first letter is capitalized. In all case, the first letter of the second and additional words is capitalized.

  • With the exception of classes, identifiers (members, parameters, methods) begin with a lower-case letter.
  • Use descriptive names of a reasonable length.

Class Naming

  • The first letter is always an upper-case letter (An Exception IS a class).
  • The header (.h) and implementation (.cxx) files are names exactly the same as the name of the class followed by the .h or .cxx extension.
  • For any class that is an interface (all methods are virtual), the name ends with Interface.
  • For any class that is an enumerated type, the name ends with Enum.

Base Class

Each class should be derived from CaretObject or QObject. CaretObject provides a method (that can be overridden) for printing information about an object and, when compiled debug, can track allocation of objects and report those that are not deleted. QObject is a parent of all Qt classes used in the Qt graphical user-interface.

Copy Constructor and Assignment Operator

If a class instance can be copied, both the copy constructor and the assignment operator should either be fully implemented and publicly accessible. Otherwise, both should be declared, without any implementation, in a private section of the header file.

Assertions

Use assertions on parameters passed to a method. In particular, on any index parameters.

The assert() function takes one parameter. If the value of the parameter is zero, abort() is called and a message listing the source code file and line number is printed. The assert function is in the header <cassert>.

A special assertion is needed assertRange(value, min-value, max-value);

Auto Pointers

Auto Pointers may be useful but must be used with caution.

Indentation

NEVER, NEVER use tabs. Instead, use 4 spaces (or 3?). Make sure any editor is setup to insert spaces in place of tabs.

One Line Does One Thing

Do not try to cram more than one operation on a single line.

If Statements

Always use brackets on if statements and else clauses. When code is being modified a programmer might add statement-B thinking that it is part of the then clause. Hover it it not. See example below. If you absolutely do not want to use brackets place the "then" statement on the same line after the if clause.

         BAD!!!!!
    if (condition)
        statement-A;
        statement-B;

         CORRECT!!!!
    if (condition) {
        statement-A;
        statement-B;
    }

         CORRECT!!!!
    if (condition) statement-A;
    statement-B;

A potential case where it DOES make sense to use a single line if statement is for things like error checking, or determining if a variable has been initialized. This helps reduce the amount of space that this kind of boiler plate uses, which increases the likelihood that a developer can fit a single logical block of code on a single page. Taking up too much space with boiler plate, while looking better, can make the code harder to understand.

Parallel Processing

Use OpenMP. The easiest way is to place the OpenMP directive on the line above a loop and have the loop consists of a single statement that calls a method.

In the User-Interface there may be cases where QThread is used.

Integers

Use the integer types from stdint.h that provide the exact size in bits (int32_t, uint64_t, etc.).

Declaring local variables and members.

  • Declare each member or local variable on its own line.
  • Declare any local variables in as small a scope as possible. There are exceptions to this rule but the situation should be exceptional.

Line Length

Beyond 80 characters is okay but try to keep it under 100.

Parenthesis

Don't be afraid to use parenthesis in conditional or mathematical statements. They remove ambiguity and may even make the code function correctly.

Parameters

When calling a method, place each parameter on a separate line. The first parameter may be on the same line as the method. The second and remaining parameters should be aligned with the first parameter (however the wiki is messing this up in the example below).


   class->methodName(firstParameter,secondParameterIsHere, andHereIsTheThirdParameter);

   class->methodName(firstParameter,
                                          secondParameterIsHere, 
                                          andHereIsTheThirdParameter);

Implementing methods

  • Doxygen comment goes first.
  • Return type is listed on next line.
  • Class::methodName and first parameter is on next line.
  • Any remaining parameters are on the additional lines.
  • Opening bracket is on a line by itself.
  • Method body.
  • Closing bracket is on a line by itself.
  
/**
 * Get a matrix element.
 * @param i   Row
 * @param j   Column
 * @return   value at [i][j]
 *
 */
double
Matrix4x4::getMatrixElement(
                   const int32_t i,
                   const int32_t j) const
{
    return this->matrix[i][j];
}

Documenting

All classes should be commented using Doxygen style comments (very similar or the same as JavaDoc) so that Doxygen can generate documentation in HTML or other formats.

The documentation for a class should describe the purpose of the class.

Since classes have both header (.h) and implementation files (.cxx), add documentation comments on methods only to the implementation of the method. In most cases, this will be inside the implementation file with the exception of inline or other short methods defined in the header file. For a method, describe the purpose of the method, each of its parameters, the values returned, and why an exception is thrown.

Member variables should be documented unless the member's name clearly describes its contents.

Use JavaDoc style commenting which begins with /** and ends with */. If the comment spans more than one line, begin each line with an asterisk.

Example Header File


/**
 * A 4x4 homogeneous transformation matrix.
 */
class Matrix4x4 : public CaretObject {

public:
    Matrix4x4();

    ~Matrix4x4();

    double getMatrixElement(
                    const int32_t i,
                    const int32_t j) const;

    void writeAsXML(XmlWriter& xmlWriter) throw (XmlException);


protected:
    /**the 4x4 matrix */
    double matrix[4][4];
};

Example Implementation File

/**
 *
 * constructor that creates an identity matrix.
 *
 */
Matrix4x4::Matrix4x4()
    : CaretObject()
{
    this->initializeMembersMatrix4x4();
}

/**
 * Destructor
 */
Matrix4x4::~Matrix4x4()
{
}


/**
 * Get a matrix element.
 * @param i   Row
 * @param j   Column
 * @return   value at [i][j]
 *
 */
double
Matrix4x4::getMatrixElement(
                   const int32_t i,
                   const int32_t j) const
{
    return this->matrix[i][j];
}


/**
 * Write the metadata in GIFTI XML format.
 *
 * @param xmlWriter The XML Writer.
 * @throws XmlException if an error occurs while writing.
 */
void
Matrix4x4::writeAsXML(XmlWriter& xmlWriter) throw (XmlException)
{
}

Personal tools
Sums Database