Program Style Guidelines


In general, the goal in programming is to write clear, readable programs that are as efficient as possible and solve a given problem. A program is not only a means of communicating with the computer, but is also a means of communicating with other people, including yourself. A program should be written so that a person who has not seen the program before, but knows the language, can read and understand the code. The following guidelines will be used in grading programs for this course and help you in achieving the goal of writing readable programs.

Visual Clarity

Program Outline

The file containing the main function should have the following basic outline:
  1. Program heading comments
  2. #include statements
  3. Constant global variables
  4. Heading comment and implementation for each function or method

Indentation

Use a uniform indentation scheme (always indent the same way) to indicate statements within control structures, nesting of control structures, and statement continuation (if a statement will not fit on one line). Indentation of 4 spaces is usual; much less is not enough and any more does not leave room for deep nesting. Avoid putting more than one statement on a line.

Braces

All braces should line up with the current level of indention. Braces may follow a control structure or appear on the next line.
    for(int i = 0; i < 10; ++i)
    {
        for(int j = 0; j < 10; ++j)
        {
            foo[i][j] = i + j;
        }
    }
Or
    for(int i = 0; i < 10; ++i) {
        for(int j = 0; j < 10; ++j) {
            foo[i][j] = i + j;
        }
    }
NOT
    for(int i = 0; i < 10; ++i)
        {
        for(int j = 0; j < 10; ++j)
            {
            foo[i][j] = i + j;
            }
        }

Spacing

Use spacing within a line to make it more readable. Use blanks around operators and other delimiters, after each comma in a list of items, and anywhere else that makes a program more readable.
    int    currentIndex     = 2;
    char   currentCharacter = 'A'
    Widget myWidget         = new Widget();

Blank lines

Use blank lines for vertical grouping of statements that logically belong together. Blank lines are useful in the following situations:
  1. Around the body of compound statements,
  2. To separate sequential statements into logical groups,
  3. To separate a control structure (if, while, for) from complex surroundings.
An excess of blank lines is not helpful. For example, do not double space your entire program.

Program, class, method, and function heading comments

Every program file, include file, and function within the program should be prefaced by a heading comment.
  1. Main program heading
     // Program:     <Program Name>
     // Author:      <Your Name>
     // Date:        <Date program was started>
     // Assignment:  <Which Program>
     // Purpose:     <A brief description of what the program does and,
     //               at a very basic level, how it does it>
     // Input:       <Describe the input expected by the program>
     // Output:      <Describe the output produced by the program>
     // Related
     // Files:       <Other files needed - header files, source files>
     // Functions:   <A list of the functions used in the program 
     //               with a brief description of each function>
     // History:     <Optional - list of modifications following 
     //               the initial implementation>
    
  2. Heading for files containing other functions and for include files
     // Filename:   <Filename>
     // Author:     <Your Name>
     // Date:       <Date code was started>
     // Assignment: <Which Program>
     // Purpose:    <A brief description of what type of functions are in
     //              the file and how they relate to other program files> 
     // Related
     // Files:      <Other files needed - header files, source files>
     // Functions:  <A list of the functions defined in this file
     //              with a brief description each function>
     // History:    <Optional - list of modifications following 
     //              the initial implementation>
    
  3. Class Heading
    // Class:         <Class Name>
    // Purpose:       <Description of the object this class models>
    // Author:        <Your Name>
    // Date:          <Date code was started>
    // Superclasses:  <List of superclasses>
    // Subclasses:    <List of known subclasses>
    // Associated
    // Classes:       <List of classes that are associated with this class>
    
  4. Method Heading
     // Method:      <ClassName::MethodName>
     // Purpose:     <A brief description of the method's behavior>
     // Author:      <Your name or whoever wrote the method>
     // Date:        <Date the method was written>
     // Parameters:  <List of the parameters expected by the method and
     //               a description of what each one means logically>
     // Returns:     <Value, if any, the method returns>
     // Pre-
     // Conditions:  <A list of conditions that must be true before
     //               the method is invoked>
     // Post-
     // Conditions:  <A list of conditions that will be true after the
     //               the method returns>
    
  5. Function Heading
     // Function:    <Function Name>
     // Purpose:     <A brief description of the function's behavior>
     // Author:      <Your name or whoever wrote the function>
     // Date:        <Date the function was written>
     // Parameters:  <List of the parameters expected by the function and 
     //               a description of what each one means logically>
     // Returns:     <Value, if any, the function returns>
     // Pre-
     // Conditions:  <A list of conditions that must be true before
     //               the function is invoked>
     // Post-
     // Conditions:  <A list of conditions that will be true after the
     //               the function returns>
    

Inline comments

You should spend some time thinking about what should be commented. Do not add comments that do not add any new information. Too many comments can be just as distracting as too few comments. Inline comments are useful in the following situations:
  1. Each constant and variable should be placed on a separate line and should be followed by a comment which describes how it is used in the program. Recall that formal parameters are documented in the function header, although it is okay to include inline documentation of them as well.
  2. The ending of a control structure in a complex section of code should be marked by a comment indented at the same level as the beginning of the control structure. e.g., the end of the body of a nested if statement or the else part of nested if's.
  3. Unclear program statements should be documented. These comments should describe the logical effect of the statements or help the programmer remember obscure facts. A comment such as:
    
    // a gets the value of b
    
    for the statement "a = b;" is useless.

Upper/lower Case

  1. Use all uppercase characters for constants:
        static const int MAXIMUM = 10; 
  2. All class and struct names begin with an uppercase letter:
        class  Widget
        struct Node
    
  3. Multi-word class and struct names begin with an uppercase letter and the first letter of each word is uppercase
        class  BigInteger
        struct ListNode
    
  4. All function, method, and variable names begin with with a lowercase letter
        int paint();
        int count;
    
  5. Multi-word function, method, and variable names begin with a lowercase letter and the first letter of each word is uppercase
        int getCurrentIndex();
        int currentIndex;
    

Understandability

Names

The names of variables, functions, types, etc. should be descriptive of their purpose. Do not be afraid to use longer names to avoid names that are short and cryptic. Some general rules:
  1. Function names can be long and descriptive since they usually appear infrequently and describe an action rather than an object.
  2. Type names can be long and descriptive since they usually appear only in variable or parameter declarations.
  3. Variable names up to 10 characters usually provide a sufficient description without cluttering up expressions.
  4. Variables used as array subscripts should be shorter if possible.
  5. Variables used only as counters, loop controls, etc., can be as short as 1 to 3 characters in length.

Complexity

Make algorithms as simple and straightforward as possible. This usually does not happen with the first implementation of an algorithm. It requires a clear understanding of the algorithm through multiple attempts/refinements. In cases where efficiency and clarity are at odds, clarity should usually win out.

Modularity

A program is easier to design/write/debug/maintain when it is broken into a group of smaller units that solve particular parts of the whole problem. All functions should be designed to do one task only. Thus, functions should be relatively small (say 50 lines or less). Any task that is repeated at several points in the program should be put in a separate function. Even tasks that are done only once, like initialization, can be put in a separate function to simplify the code. Your main function will normally be a few function calls and perhaps some simple control structures.

Global variables

No global variables will be used. Any communication between a function and its caller will be done through parameters and/or the function's return value. The use of global variables often introduces hard-to-find logic errors and indicates a poorly organized program. There are circumstances where global variables may be used, but we will not see those circumstances in this course.

Runtime behavior

Robustness

A program that does not terminate abnormally when given erroneous input data is robust. Input validation can require extensive programming and some errors may still not be detected. The amount of input validation necessary depends on the reliability of the input source.

Error handling

When an error is detected at runtime, usually an input error, the program should report the error in an informative manner and continue useful processing. If the program cannot continue useful processing, it should terminate as gracefully as possible.

Output formatting

A program's usefulness is generally measured by its output. Output should be readable by the program user. Any output data should be accompanied by a description or put into tabular form with appropriate headings.

Generality

Programs are not static creatures. They should be designed to accommodate change. Avoid using hard-coded constants, use constant variables or read the values from the user. A general function is easier to use in another program. Related functions should be grouped together in separate source files and related declarations should be grouped in include files. If you are smart about the way you write programs, you will rarely have to start from scratch when starting a new program. Reuse code when possible.