Purpose

This quick style guide is designed as an aid when you are programming. It lays out the style standards we expect you to practice in your first year programming course.

The purpose of style is to make programs easier to read and understand. Programs are not just written for oneself. Modern programming teams often have large numbers of people. Moreover, the average lifetime of a piece of code is ten years. Thus more time (and therefore money) may be spent on maintaining a piece of code than was spent originally creating it. Consequently, we need to make code as readable as possible for

  1. Other members of our programming team
  2. Engineers tasked to maintain our code long after we are gone
  3. Ourselves, perhaps coming back to our code a year or two after we wrote it.

While many organizations seek to make their code understandable by using auxiliary documentation, bitter experience has shown that auxiliary documentation seldom gets updated when code gets changed. Thus it is important to make code as self-documenting as possible. Good style is an important means of achieving that goal.

The guide is divided into four parts.

Comments

Comments are written for people (see list above). The compiler throws them away. Thus they are the first-line tool in making our code files self-documenting. Comments should be used in the following ways:

File Header

This appears at the beginning of every file. It's purpose is to document when this file was created and by whom. For your assignments we would like you to use this format.

Note that we want header comments set off by starting them with a

/****** fileName.ext *************************************************************

and terminating them with

*********************************************************************************/

In addition each line inside the block should start with a * . Please make sure you provide all the information indicated.

Function Header

Similar in appearance to a file header, its purpose is to give a description of the function in a standard way. An example appears below.

Note that the name of the function should be embedded in the top star bar. Sections include

@params:
Name and description, including any relevant units, of each parameter, in order. The description should be in the client's terms (i.e., with respect to the problem being solved by this function). Omit iff (if and only if ) there are no parameters.
@pre:
short for precondition, which is something that this function assumes to be true. Usually this is attached to one or more parameters to describe restrictions on the range of values the function client may send in (e.g., only positive values for a square root function). Omit iff there are no restrictions.
@modifies
a description of any changes made by this function that are visible from other parts of the system. For example, if a function changes the value of a global variable or a reference parameter then describe the new value given to that variable. Omit iff no externally observable changes are made.
@returns:
a description of what value is returned, including relevant units. Omit iff return type is void.

Multiline Comments

These are typically used to explain how a section of code works. They should used iff the working of the section of code is not obvious to a reasonably experienced programmer.

They may also be used in place of mutiple single line comments where a single line comment is too long.

Should appear before the piece of code being explained.

Single Line Comments

Often used to the right of a variable declaration when the name of the variable is not enough to make its use self-evident. If a little too long to appear on the same line, can be used just before the declaration instead.

Also used just before an instruction to explain it at that point. For example

double cascade(double a1, double a2, double a3){
     return -a1*(-a2)*(-a3);
}

is function to compute the combined gain of three inverting amplifiers (a "cascade"). It might better be rendered as

double cascade(double a1, double a2, double a3){
     // three inverting amps in a row produce a negative gain
     return -a1*a2*a3;
}

where the result of three minus signs muliplied together is of course a negative. While every programmer knows that, not all programmers would know that inverting amps have negative gains (which requires electrical engineering knowledge).

The single line comment explains that. The resultant equation is cleaner than the first version and requires two less operations.

Overusing Comments

This generally occurs in first year programming courses generally on the grounds that if my instructors want comments I'll give them *&#@$! comments! Here's a case in point.

A good rule of thumb is to tell your readers something they might not know.

White Space

White space includes spaces, tabs and new lines. Judicious use of white space can markedly improve a program's readability. Here's some rules:

  1. Only one instruction per line, please.
  2. Only one declaration per line, please.
  3. Separate major sections of code with an empty vertical line
  4. Make judicious use of single spaces to increase the readability of expressions, for example to separate terms in an expression e.g.
    a + b*x
    instead of a+b*x or a + b * x.
  5. Indent every time you start a new block. Your editor will try do this automatically but can get fooled, so you may have to fix it up. Backdent when you leave the block.
  6. Be consistent in how you use block operators '{' and '}'.

With regard to the last rule any of the following usages of the curly brackets are acceptable. Just stick to one however.

Naming

Programmers give names to constants, variables, functions and classes, although in this course we'll focus only on the first two. Most of the time, names should be nmemonic, that is, self descriptive.

Constant Names

Constant names should be in capitals, with underscores to separate parts visually, as

const double PI = 4 * atan(1.0);
const double DELTA_T = .001;    

Variable Names

Variable names should always be in camelCase, that is lower case, except for the first letter of embedded words which should be uppercase; notwithstanding that, the variable name itself should start with a lower case. For example—

int startingBalance;	// in pennies
int closingBalance;	// in pennies

String firstName;
String familyName;

Notice the crucial short comment added to the first two declarations providing the information that the monetary amount is to be stored in pennies.

i, j and k are often used as integer counting variables and n is often used as a number of things or a size. For example

for (int i = 0; i < n; i++) { ....

is undoubtedly the most commonly encountered form of a for loop. Similarly, in mathematical applications (such as algebra or graphics) x, y and z are common names for double variables. Such usage is perfectly acceptable so long as the variables are used in a general sense (as in algebra) or by convention, for example—

// The co-ordinates of a point in 3-D space.
double x;
double y;
double z;

They should not be used when a more particular usage is being implemented. For example—

double getSlope(double rise, double run);

For the particular case of computing a slope, the terms rise and run are more descriptive than y and x.

Function Names

The rules for function names are similar to variable names:

  1. Start with a lowercase letter
  2. Use camelCase
  3. Make the name descriptive of what the function does.

Note most functions represent actions (in which case they are verbs) while variables tend to represent things (nouns).

Functions that return a bool (true of false) should start with the word "is" as

bool isOn();
bool isOpen();   

Consider starting simply value returning functions (functions that read a value from somewhere as opposed to calculating it using an expression) with a "get"

int getWidth();
double getBalance();   

Anytime you do use a naming system, such as starting value reading functions with "get" and bool reading functions with "is", make sure you do so consistently.

Structure

Structure refers to the way code is constructed, primarily with regard to conrol structures like for loops and if-then-else SInce we are just starting that topic, we'll add more to this later.

Creating Variables

Avoid creating unnecessary variables. For example—

double quadratic(double x, double a, double b, double c){
    double term1 = a*x*x;
    double term2 = b*x;
    double term3 = c;
    return term1 + term2 + term3;
}

There is absolutely no good reason to create the three term variables. term3 is particularly bad as all it amounts to is a creation of an exact copy of c. The following code is simpler, easier to read and easier to maintain.

double quadratic(double x, double a, double b, double c){
    return a*x*x + b*x + c;
}

A good rule of thumb is to create variables where their value is going to be used more than once. For example, this code fragment —

    double radical = sqrt(b*b - 4*a*c)/(2*a);
    double bOver2A = b / (2*a);
    cout << "the first root is " << (-b + radical)/(2*a);
    cout << " while the second is " << ((-b - radical)/(2*a);

is preferable to this one —

    cout << "the first root is " << (-b + sqrt(b*b - 4*a*c))/(2*a);
    cout << " while the second is " << ((-b - sqrt(b*b - 4*a*c))/(2*a);

because the computation of the radical is very expensive so that computing it once and saving its value in a variable is much better than computing it twice. This—

    double radicalBy2A = sqrt(b*b - 4*a*c)/(2*a);
    double bBy2A = -b / (2*a);
    cout << "the first root is " << bBy2A + radicalBy2A;
    cout << " while the second is " << bBy2A - radicalBy2A;

is even more efficient, though perhaps at some small cost in readability.