[Top] [Contents] [Index] [ ? ]

AnswerFinder programming guidelines

AnswerFinder programming guidelines

AnswerFinder project http://www.ics.mq.edu.au/~diego/answerfinder

Copyright 2006, Menno van Zaanen, Macquarie University.

Most of a programmer's efforts are aimed at the development of correct and efficient programs. But the readability of programs is also important. There are many "standards" in use. Since following them will not guarantee good code, these "standards" are actually guidelines of style. Each one has its proponents and detractors. This document collects a summary of guidelines for writing and commenting the AnswerFinder code. The essential point is that a program is a medium of communication between humans; a clear, consistent style will make it that much easier to communicate.


1. Important


1.1 General

When you write a program, ask yourself these questions:


1.2 Common-sense Rules


1.3 General Documentation


2. Program Documentation


2.1 Program Heading

The main program file should begin with a comment section in the following form and with the following information filled in:

 
////////////////////////////////////////////////////////////////////////////////
// Filename: < filename >
////////////////////////////////////////////////////////////////////////////////
// This file is part of the AnswerFinder package.
////////////////////////////////////////////////////////////////////////////////
// < Description of what is in the file >
////////////////////////////////////////////////////////////////////////////////
// $Log:$
////////////////////////////////////////////////////////////////////////////////

The end of the file should contain a line indicating that the file ends there:

 
// end file: < filename >

2.2 Preprocessor Section

In the preprocessor section, include statements for header files should have comments indicating the types, constants, variables, or functions used from the header. For example,

 
#include <iostream> // cin, cout, <<, >>, endl
#include <cmath> // sin, cos
#include "list.h" // List

2.3 Function Headings

Include documentation, as needed, of the following form for each function:

 
////////////////////////////////////////////////////////////////////////////////
// Function: < Name of function >
// < Short description of what function does in terms of the received
//   parameters >
// < Assumptions about the state or values of the received parameters >
////////////////////////////////////////////////////////////////////////////////
void
sampleFunction(…) {
  …
} // end function: sampleFunction

2.4 Group Ends

Comment the ending curly brace of each compound statement if needed for clarity. Such comments should be quite brief, mnemonic, and UNIQUE within the function or main program. For example,

 
////////////////////////////////////////////////////////////////////////////////
// Function: try
// Attempts to do some things…
////////////////////////////////////////////////////////////////////////////////
void
try(…) {
  …
  while (!done) {
    …
  } // end while: done is not yet true
  …
} // end function: try

Always comment the end of functions, struct, and class declarations.


2.5 Comment Use

Comment code to improve clarity. Comments should tell WHAT is being done or why it is being done, not how it is being done. For example,

 
i = i - 1; // Adjust i to point to the end of the previous word:

is better than

 
i = i - 1; // Subtract 1 from i:

Often these comments will be phrases found in the analysis and design.


2.6 English

Comments should be in good English. Grammar and spelling should be correct.


2.7 Abbreviations

Abbreviations in comments should rarely be used, and then only those that would be found in a standard dictionary.


3. Names


3.1 Language

All names should be written in English. English is the preferred language for international development. Only use widely accepted abbreviations (e.g. those that you would find in a dictionary).


3.2 Name and Scope

Variables with a large scope should have long names, variables with a small scope can have short names. A programmer reading short named variables should be able to assume that its value is not used outside a few lines of code. Common scratch variables for integers are i, j, k, m, n and for characters c and d.


3.3 Types

Names representing types must be in mixed case starting with upper case: Line, SavingsAccount. This is common practice within the C++ development community.


3.4 Variables

Variable names must be in mixed case starting with lowercase: line, savingsAccount. This is common practice within the C++ development community. It makes variables easy to distinguish from types, and efficiently resolves potential naming collision as in the declaration,

 
Line line;

3.5 Constant Names

Named constants (including enumeration values) must be all uppercase using underscore to separate words: MAX_ITERATIONS, PI. This is common practice within the C++ development community. In general, the use of such constants should be minimised. Never use #define to define constants. Always use the type safe const <type> notation. In some cases implementing the value as a method may be an even better choice. Instead of,

 
const int MAX_ITERATIONS = 25;

You could write,

 
////////////////////////////////////////////////////////////////////////////////
// Function: getMaxIteration
// Returns the number of maximum iterations.
////////////////////////////////////////////////////////////////////////////////
int
getMaxIteration() {
  return 25;
} // end function: getMaxIteration

This is especially important if you think the "constant" value may change in the future.


3.6 Methods and Functions

Names representing methods or functions must be verbs and written in mixed case starting with lowercase: getName(), computeTotalWidth(). This is common practice within the C++ development community. This is identical to variable names, but functions in C++ are already distinguishable from variables by their specific form.

Typical verbs used are:

get
set

When an attribute is accessed directly.

compute

When there is some (possibly time-consuming) operation.

find

When there is a simple look up method with a relatively small number of operations involved.

initialize

The American spelling should be preferred. Abbreviations (e.g. init) should be avoided.


3.7 Namespaces

Names representing namespaces should be all lowercase: analyzer, iomanager, mainwindow. This is common practice in the C++ development community.


3.8 Template Types

Names representing template types should be a single uppercase letter:

 
template<class T> …
template<class C, class D> …

This is common practice in the C++ development community. This makes template names stand out relative to all other names used.


3.9 Common Prefixes and Suffixes

The suffix List or Array can be used on names representing lists or arrays: vertexList, itemArray. Simply using a plural form should be avoided since it is difficult to distinguish from the corresponding singular form.

The prefix n should be used for names representing a number of objects: nPoints, nLines. The notation is taken from mathematics where it is an established convention for indicating a number of objects.

The suffix No should be used for variables representing an entity number: tableNo, employeeNo. The notation is taken from mathematics where it is an established convention for indicating a number of objects. An elegant alternative is to prefix such variables with an i: iTable, iEmployee. This effectively makes them named iterators.


4. Variables and Constants


4.1 Global Declarations

Constants should be declared globally if there is a possibility of using them in more than one function, otherwise they should be declared locally to the function that uses it. While there are valid reasons for having global variables, they generally should be avoided.


4.2 Function Variable Identifiers

Each (non-class attribute) variable identifier that occurs in a function should be local to that function - that is, declared in the function's header or declaration part.

  1. If the variable may have its value changed in the body of the function and that new value will be needed back in the calling program (i.e., it is passed back), then the variable should be declared as a reference formal parameter.
  2. If the variable gets its initial value from the calling program but does not send a different value back (i.e., it is only received), then the variable should be declared as a value formal parameter, except for C++ arrays, which are automatically passed as reference parameters. Also when efficiency of copying is a concern, large structures like structs or class objects should be declared as reference formal parameters. Such reference formal parameters should be declared as const.
  3. If the variable does not get its initial value from the calling program and does not pass its value back (via a parameter), then the variable should be declared as a local variable of the function. This generally includes the returned object, if any. (Take care not to return a pointer or reference to a local variable!)

4.3 Constants

Constants in your algorithm should be replaced by constant identifiers in your program. Exceptions should be made only when the constant conveys its own meaning, such as 0 as an initial value for a sum or 1 to start a count, or is part of a constant mathematical formula, such as 2 in 2 * PI * r.


4.4 Pointers and References

Pointers and references should have their reference symbol next to the variable name rather than to the type name:

 
float *x; // NOT: float* x;
int &y; // NOT: int& y;

It is debatable whether a pointer is a variable of a pointer type (float* x) or a pointer to a given type (float *x). Important in the recommendation given though is the fact that it is impossible to declare more than one pointer in a given statement using the first approach. I.e. float* x, y, z; is equivalent to float *x; float y; float z;. The same goes for references. Note, however, that variables should always be declared on a new line in a new statement.


5. Program Formatting


5.1 Statements Outside Function Body

Any preprocessor statements (#include, #define, etc.) should be at the beginning of a file (after the program file heading comment). Any typedef type declarations should follow, then any global constants and static variables. Finally, function prototypes should appear just before the main function. No other statements should appear outside a function body.


5.2 Local Declarations

All local constants and local variables should be declared just before they are needed. By doing this, a variable will only be available in the minimum scope it can be. For example, variables that are only used inside a loop are only available within that loop.


5.3 Blank Lines

A blank line should be used to separate declarations from the executable statements. In general, blank lines should be used wherever their use will improve readability. Use two blank lines to separate function, struct and class definitions and declarations.


5.4 Indenting

Indenting should be used to convey structure. A level of indentation should be exactly 2 spaces. Indenting should be consistent. Normally, { increases the level of indentation with one and } decreases it.


5.5 Groups

Always scope brackets for the blocks in a control structure, even if the block contains one sentence only:

 
if (num > 0) {
  cout << "The number is positive" << endl;
}

This way there is less re-editing to do if the block size grows larger than one statement. Less re-editing means less chance for bugs, and less file version differences when using source code control.


5.6 Declarations

For declarations, each identifier should be declared on a separate line. The type identifier should be indented.

For example, in the main function, we might declare

 
int
main(void) {
  const int MAX_SIZE = 100;
  const float PI = 3.14159;
  int i; // Outer loop index
  int j; // Inner loop index
  int testArray[MAX_SIZE]; // Array of test scores
  Point p1;
  …
} // end function: main

Note that variables should only be declared just before they are needed.

Also, comments should explain the function of each variable where appropriate.


5.7 Function Heading

In a function heading, there should be one formal parameter per line, lined up under each other as shown below. Comments about the parameters should go in the comment section of the function.

 
void
findItem(int &item,
         int position)

5.8 Width

A statement should not be longer than a screen's width (80 characters). If a non-I/O, non-function call statement must be continued on more than one line, the second line should be indented and successive continuation lines should be aligned with the second line of the statement. For example, we might write

 
while ((('a' <= line[i]) && (line[i] <= 'z'))
      || (('A' <= line[i]) && (line[i] <= 'Z'))) {
  i++;
}

The indentation of the loop expression should be more than a regular indentation level. Also, the operator that links the sub-expressions should be on a new line, to show that it's a continuing expression.

An I/O statement should be broken up so that the << or >> operators line up. For example, we might write

 
cout << setw(15) << name
     << setw(30) << address
     << setw(15) << phone << endl;

A function call statement should be broken up so that the function arguments are lined up. For example, we might write

 
void
computeSample(argument1, argument2, argument3,
              argument4, argument5, argument6);

5.9 Control Statements

For the statement that follows if, else, while, for, do, and switch: The statement should start on the next line and be indented. For example,

 
if (first <= last) {
  found = true;
}

5.10 Switch Statements

Use the comment Fallthrough if a case keyword does not have a break statement. Leaving the break out is a common error, and it must be made clear that it is intentional when it is not there:

 
switch (condition) {
case ABC:
  statements;
  // Fallthrough
case DEF:
  statements;
  break;
default:
  statements;
}

Don't indent the case labels, but do indent the statements within each case.


5.11 Block Alignment

Closing curly braces should match the indentation level of the statement that contained the open curly brace. Remember that all compound statements (that contain other statements) should use curly braces.

Each line of the body of a compound statement should be indented. For example,

 
if (a[middle] == item) {
  item = a[middle];
  found = true;
  position = middle;
} // end if: match found

5.12 Conditionals

Column alignment should be observed for each set of reserved words if and else. This include multi-branch constructs. However, this should be clear, because the open curly brace already results in a higher indentation level. For example:

 
if (x > 90) {
  grade = 'A';
}
else if (x > 80) {
  grade = 'B';
}
else if (x > 70) {
  grade = 'C';
}
else if (x > 60) {
  grade = 'C';
}
else {
  grade = 'F';
}

5.13 Comments

Comments that describe one or more statements should be immediately above and aligned with the statement or collection of statements which they describe. For example,

 
j = i;
while ((j > 1) && (a[j - 1] > a[j])) {
  // a[1..j - 1] is unsorted and a[j..i] sorted:
  swap(a[j], a[j - 1]);
  --j;
} // end while

5.14 Main Curly Braces

The curly braces for functions should be similar to their use in conditional statements. For example,

 
void
findMinIndex(…) {
  …
} // end function: findMinIndex

5.15 Blank Spaces

At least one space should be used in the following locations within C++ text (this does not apply within comments and character strings):

This should lead to code that looks like:

 
if ((foo == 0) && (!bar)) {
  getFooBar(&foo, &bar);
}

5.16 Function Size

A function should fit on one screen (about 25 lines) if possible and must fit on a listing page (about 50 lines). Ideally, the analysis and design will not produce code that is more than a page long, but if the code does not fit initially, introduce one or more new functions to split up the work in logical places. This, of course, is not a strict rule, more a rule of thumb.


6. Class Files


6.1 Reusability

Class definitions and implementations should be divided into multiple files so that we can reuse them easily. By convention, the class definition is stored in a header file which has the extension .h. The implementation of the class member functions are stored in a source file with the extension .cpp. The main program is stored in a separate source file that includes the header files for each class used.


6.2 Inclusion of Header File

Every class header file should use compiler directives #ifndef, #define, and #endif to ensure a header file is only included once. The symbol should be the name of the header file in all lower-case letters with an underscore (_) replacing the dot and two initial and trailing underscores. For example, for the header file counter.h, the directives would be:

 
#ifndef __counter_h__
#define __counter_h__

////////////////////////////////////////////////////////////////////////////////
// Class: Counter
// Stores some things…
////////////////////////////////////////////////////////////////////////////////
class Counter {
  …
}; // end class: Counter

#endif // __counter_h__

6.3 Header File Documentation

Every header file should start with a comment block with the following information filled in:

 
////////////////////////////////////////////////////////////////////////////////
// Filename: < filename >
////////////////////////////////////////////////////////////////////////////////
// This file is part of the AnswerFinder package.
////////////////////////////////////////////////////////////////////////////////
// < Description of what is in the file >
////////////////////////////////////////////////////////////////////////////////
// $Log:$
////////////////////////////////////////////////////////////////////////////////

The end of the file should contain a line indicating that the file ends there:

 
// end file: < filename >

6.4 Function Prototypes

In class definitions, the qualifiers public, protected and private should not be indented and the member function prototypes and data member declarations should be indented. Data members should start with an underscore. Free function prototypes should appear after the class definition. For example,

 
////////////////////////////////////////////////////////////////////////////////
// Class: Counter
// Stores some things…
////////////////////////////////////////////////////////////////////////////////
class Counter {
friend …
public:
////////////////////////////////////////////////////////////////////////////////
// Function: Counter
// Constructor
////////////////////////////////////////////////////////////////////////////////
  Counter();

////////////////////////////////////////////////////////////////////////////////
// Function: Increment
// Increments the counter by 1
////////////////////////////////////////////////////////////////////////////////
  void
  Increment();
  …

protected:
private:
////////////////////////////////////////////////////////////////////////////////
// Variable: _value;
// Current value of the counter
////////////////////////////////////////////////////////////////////////////////
  int _value;
}; // end class: Counter


////////////////////////////////////////////////////////////////////////////////
// Function: operator>>
// bla
////////////////////////////////////////////////////////////////////////////////
istream &
operator>> (istream &in, Counter &theCounter);


////////////////////////////////////////////////////////////////////////////////
// Function: operator<<
// bla
////////////////////////////////////////////////////////////////////////////////
ostream &
operator<< (ostream &out, const Counter &theCounter);

6.5 Function Documentation

In class definitions, short comments describing what member functions do and what member data represent should be included as shown above.


6.6 Constant Functions

Member functions that do not change the state of the object should be declared as const. For example,

 
////////////////////////////////////////////////////////////////////////////////
// Class: Counter
// Stores some things…
////////////////////////////////////////////////////////////////////////////////
class Counter {
public:
////////////////////////////////////////////////////////////////////////////////
// Function: getValue
// Returns the current value of the counter
////////////////////////////////////////////////////////////////////////////////
  int
  getValue() const;
  …
} // end class: Counter

If needed (in abstract classes), certain member functions should be declared = 0.


6.7 Class Documentation

Every class implementation file should start with a comment block with the following information filled in:

 
////////////////////////////////////////////////////////////////////////////////
// Filename: < filename >
////////////////////////////////////////////////////////////////////////////////
// This file is part of the AnswerFinder package.
////////////////////////////////////////////////////////////////////////////////
// < Description of what is in the file >
////////////////////////////////////////////////////////////////////////////////
// $Log:$
////////////////////////////////////////////////////////////////////////////////

The end of the file should contain a line indicating that the file ends there:

 
// end file: < filename >

6.8 Order

Class member, friend, and overloaded function implementations should appear in the same order as presented in the class specification and class definition.


6.9 Function Comment Headers

Function comment headers as described above should be included with member function definitions. If there are many function definitions, comments indicating grouping are helpful.


Concept Index

Jump to:   A   B   C   D   E   F   G   H   I   L   M   N   O   P   R   S   T   V   W  
Index Entry Section

A
Abbreviations2.7 Abbreviations

B
Blank Lines5.3 Blank Lines
Blank Spaces5.15 Blank Spaces
Block Alignment5.11 Block Alignment

C
Class Documentation6.7 Class Documentation
Class Files6. Class Files
Comment Use2.5 Comment Use
Comments5.13 Comments
Common Prefixes and Suffixes3.9 Common Prefixes and Suffixes
Common-sense Rules1.2 Common-sense Rules
Conditionals5.12 Conditionals
Constant Functions6.6 Constant Functions
Constant Names3.5 Constant Names
Constants4.3 Constants
Control Statements5.9 Control Statements

D
Declarations5.6 Declarations

E
English2.6 English

F
Function Comment Headers6.9 Function Comment Headers
Function Documentation6.5 Function Documentation
Function Heading5.7 Function Heading
Function Headings2.3 Function Headings
Function Prototypes6.4 Function Prototypes
Function Size5.16 Function Size
Function Variable Identifiers4.2 Function Variable Identifiers

G
General1.1 General
General Documentation1.3 General Documentation
Global Declarations4.1 Global Declarations
Group Ends2.4 Group Ends
Groups5.5 Groups

H
Header File Documentation6.3 Header File Documentation

I
Inclusion of Header File6.2 Inclusion of Header File
Indenting5.4 Indenting

L
Language3.1 Language
Local Declarations5.2 Local Declarations

M
Main Curly Braces5.14 Main Curly Braces
Methods and Functions3.6 Methods and Functions

N
Name and Scope3.2 Name and Scope
Names3. Names
Namespaces3.7 Namespaces

O
Order6.8 Order

P
Pointers and References4.4 Pointers and References
Preprocessor Section2.2 Preprocessor Section
Program Documentation2. Program Documentation
Program Formatting5. Program Formatting
Program Heading2.1 Program Heading

R
Reusability6.1 Reusability

S
Statements Outside Function Body5.1 Statements Outside Function Body
Switch Statements5.10 Switch Statements

T
Template Types3.8 Template Types
The Most Important Points1. Important
Types3.3 Types

V
Variables3.4 Variables
Variables and Constants4. Variables and Constants

W
Width5.8 Width

Jump to:   A   B   C   D   E   F   G   H   I   L   M   N   O   P   R   S   T   V   W  

[Top] [Contents] [Index] [ ? ]

Table of Contents


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated by Diego Molla on February, 20 2007 using texi2html 1.76.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ < ] Back previous section in reading order 1.2.2
[ > ] Forward next section in reading order 1.2.4
[ << ] FastBack beginning of this chapter or previous chapter 1
[ Up ] Up up section 1.2
[ >> ] FastForward next chapter 2
[Top] Top cover (top) of document  
[Contents] Contents table of contents  
[Index] Index index  
[ ? ] About about (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated by Diego Molla on February, 20 2007 using texi2html 1.76.