Operating Systems Principles

480/580 Coding Standards


Last updated Sun. 1/14/2018
Back to 480 home page
Back to Reva Freedman's home page

Summary

Coding standards, including formatting and documentation, are important because the human reader is one of the most important users of program source.

Main purposes of documentation include helping the reader to finds section of code and enabling the reader to understand code faster.

Secondarily, documentation can be useful in helping the reader to understand something that is not clear. If a large amount of explanation is required, it may be better to rewrite the code.

These rules have been set up to create the most clarity while reducing redundant documentation as much as possible.

Corrections and suggestions are invited.

Program Organization

  • Program elements should occur in the following sequence:
  • Main program documentation
    #include statements
    symbolic constants
    function prototypes
    main program
    functions
    

        Class definitions will generally go in their own files, but shouid precede function prototypes if used in a single compilation unit.

        Global variables are often a bad idea, but should follow function prototypes if used in a single compilation unit.

    Overall Program Formatting

  • Line width should be optimized for the human reader. Therefore in general lines should not exceed 78 characters.
  •     This applies to comments as well as code.

  • Consistency is more important than any specific rule.
  • Program Header

  • A header similar to the following should appear at the top of your main program:
  • /********************************************************************
    Class:     CSCI 480-2
    Program:   Assignment 1
    Author:    Your Name
    Z-number:  z1234567
    Date Due:  mm/dd/yy
    
    Purpose:   A short indication of what the program does, e.g.:
               Read and format relevant data from /proc file.
    
    Execution: Command to execute your program
               (should match directions on assignment sheet)
    
               ./hw1.exe [filename]
               If filename is omitted, /proc/xxx is used.
    
    Notes:     (optional) any special notes to your T.A. or other readers
    
    *********************************************************************/
    

  • In this example, and all the examples of headers below, the lines of stars can be eliminated if you use the '//' version of comments instead of block comments.
  • Format of Names

  • Names of variables and functions may use one of two formats:
  • Name format should be consistent within a program.
  • Class names should also follow one of the two formats above, but the first letter should be capitalized.
  • Variable Names

  • In general, the base of a variable name should be a noun, with adjectives used to make it specific, e.g., avg_height.
  • Names should be descriptive, e.g., avg_height rather than h or hgt.
  • In general, abbreviations should be avoided; as above, height is preferable to hgt. Abbreviations can be useful for long or frequently repeated words.
        If abbreviations are used, they must be spelled consistently throughout your program, i.e., if you use avg_height for average height, then you should use avg_weight for average weight and not ave_ or average_.

  • In general, names of pointers of addresses should be identified as such, e.g., xyz_ptr or addr_of_xyz.
  • Temporary variables

  • The exception to this rule is for temporary variables that have no intrinsic meaning, such as subscripts and loop counters.
  • for (i = 0; i < 10; i++) ...
    

    Symbolic constants

  • Use the C++ form for symbolic constants. Capitalize all symbolic constants.
  •      const int MAX_STU = 40;
    

    Function Names

  • In general, function names should start with a verb and state what that verb refers to, e.g., count_lines().
  • The same rules on abbreviations for variable names apply to function names as well.
  • Comment Format

  • The following form is preferred because it makes it clearer which lines are comments.
  • // some comment
    // more comments
    // even more comments
    

        This form is also acceptable and can be more convenient for doc boxes at the top of a program or function.

    /*
    some comment
    more comments
    even more comments
    */

    Section Documentation

  • Each section of code should be preceded by a comment that explains what the code does or what that group of variables is used for.
  •     The following examples show the size of chunk that should be commented.

    // Loop to accept and process user-supplied glucose measurements
    
    // Decide if gizmos or widgets are to be used
    
    // Calculate and store averages and standard deviations of measurements
    

        Some programs are longer or more complex than others. That means that main() may have several sections while a function that only does one thing may have only one.

        Occasionally, for a complex formula, a section will be only one line long:

    // calculate the area of the triangle: semi is semiperimeter
    // s1, s2, and s3 are sides 
    
    area = sqrt(semi * (semi - s1) * (semi - s2) * (semi - s3));

  • Section documentation should be preceded and followed by a blank line. Additional blank lines before logical divisions of the program and before functions may be profitably used to indicate the structure of the program. Be consistent.
  • Section documentation should always start in column 1.
  • It is rarely but occasionally useful to put a comment on the same line as code.
  •  ...
        }    // end I/O loop
    
        If you find yourself frequently needing such comments, you should consider changing your nesting style.

    Documentation of variables

  • Variables should be organized into groups, and each group should be labeled as to their purpose.
  • // Item subtotals
         int   tot_items;
         float tot_cost;
    

        Horizontal alignment of variable names, as in the above examples, is encouraged but not required.

    Indentation

  • Code must be indented using one of the methods shown. Method 1 is preferred.
  • Each level of nested blocks must be indented under its parent.
  • You must use the same method throughout your program.
  • Method 1 (preferred)

    The following method is recommended:

    if (condition)                   
      {
        statement1;
        statement2;
      }
    else
      {
        statement3;
        statement4;
      }
    
    while (condition)
      {
        statement 1;
        statement 2;
      }
    
    

    If you use method 1, indent two spaces as shown.

    Methods 2 and 3 are less desirable since they do not show indentation as clearly. If you use methods 2 or 3, two spaces are preferred; four is acceptable.

    Method 2

    if (condition)                   
    {
      statement1;
      statement2;
    }
    else
    {
      statement3;
      statement4;
    }
    
    while (condition)
    {
      statement 1;
      statement 2;
    }
    

    Method 3

    if (condition)                   
      {
      statement1;
      statement2;
      }
    else
      {
      statement3;
      statement4;
      }
    
    while (condition)
      {
      statement 1;
      statement 2;
      }
    

    Additional methods

    Other brace styles put the opening brace on the same line as the if, else or while.
    These are more difficult to read because opening and closing braces do not line up.
    These are permitted if you are used to them and prefer them.

    Anyone who thinks that their preferred style is the only style or only logical style are encouraged to consult an exhaustive list of possible brace styles before making this assertion.

    Continuation lines

  • If a function header or function call requires more than one line, the second and succeeding lines should be indented under the first argument of the function:
  • int fn(long_name1, long_name2, ...,
           long_name99)
    

        Similarly, arithmetic expressions that overflow should be aligned under the preceding arithmetic symbol (+, etc.).

        Likewise, I/O statements (cin or cout) statements that overflow should be aligned under the preceding I/O operator (<<, >>).

    Tabs and spaces

    Spaces are better than tabs for indenting because they will display correctly in any configuration.

    Any good editor will have a setting that prevents spaces from being converted to tabs.

    If you use tabs, you are responsible for making sure your program will display correctly on turing/hopper. Unix defaults to tabs every 8 characters.

    Horizontal white space

  • White space should be used before and after '=' and comparison operators ('= =', '<', etc.):
  • for (i = 0; i < 10; i++)
    

  • White space should be used after a comma or semicolon that is not the last character on a line. There should not be a space before the comma or semicolon.
  • total = calcTotal(amt, taxRate, tip);
    

  • Do not put white space after a left parenthesis or before a right parenthesis.
  • Functions

  • Functions should be documented like sections, plus some indication of the arguments and return value. If the function updates one or more of its arguments (or values they point to), that should be noted also.
  • /***************************************************************
    Calculate the area of a triangle using Hero's formula
    
    Arguments: sides of the triangle
    
    Returns:  the area of the triangle
              -1 if the lengths do not represent a valid (closed) triangle
    
    Additional section documentation as required.
    
    ***************************************************************/
    

  • Getters and setters should be grouped together and identified but they do not need descriptions since their function is known. Similarly, constructions should be labeled but they only need a description if their function is non-obvious.
  • /***************************************************************
    
    Getters for class_name
    
    ***************************************************************/
    

    Header Files

  • Every class should have a header file named xyz.h, where xyz is the name of the class or a logical variant thereof.
  • Header files should start with a documentation box containing the following information:
  • /****************************************************************
       Class_name header
       (or description of resources in header)
    
       Author:    Your Name
       Z-number:  z1234567
    
       Description: purpose of the class
    
       (optional) Any other information needed by the user
    ****************************************************************/
    

  • Classes should always have header guards to prevent duplicate inclusions.
  • In general, data members should be private. Functions should be public if they are part of the interface, i.e., functions should be public unless they are for internal use only.
  • Member names should be indented two spaces under the headings public and private.
  • Whether variables should be documented individually or can be documented as a group depends on clarity. For example, if several variables have been defined for an item, then a group of subtotals for those variables could simply be labeled as "group-level subtotals for ...".
  • Class Method Files

  • Every class should have a method file named xyz.cpp, where xyz is the name of the class or the same logical variant as the header file.
  • Class method files should have a header identifying them:
  • /****************************************************************
       Class_name
    
       Author:    Your Name
       Z-number:  z1234567
    
       Description: purpose of the class
    
       (optional) Any other information needed by the user
    ****************************************************************/
    

  • Class method files consist of functions. These functions should be documented as any other functions.
  • Makefiles

  • Makefiles should start with a header like this:
  • # Course:    CSCI 480-2
    # Program:   Assignment 1
    # Author:    Your Name
    # Z-number:  z1234567
    # Date Due:  mm/dd/yy
    
    # Notes:     (optional) further notes if needed
    

  • Each rule or group of related rules should be preceded by a comment line, as in this makefile example.
  • C++ Constructs

  • Use only C++ constructs.
  • Do not use C functions such as printf().
  • Do not use unsafe constructs such as strtok().
  • Do not use 1 and 0 for true and false.
  • Use the C++ string class for strings. Do not use C-strings, i.e., arrays of characters, except to interface with the operating system.
  • Restricted Constructs

  • Break may only be used to escape from a while (true) I/O loop. Although the use of switch is discouraged, break may also be used after each case of a switch.
  • Goto should never be used.
  • Good Practices

    The following good practices are encouraged because they simplify program debugging and updating. However, they are not required.

  • Declare every variable on a separate line, since
  • int avg_height;
    int total_height;
    

         is easier to update than

    int avg_height,
        total_height;
    

  • Use temporary variables when it might be useful to examine a field when debugging. For example,
  • total_area = (complex formula)
    return total_area
    

         is easier to debug than

    return (complex formula)
    

  • In general, don't nest if or while statements more than three deep.
        Although the compiler can read it, most human beings have to count on their fingers by that point.
  • If you use the /* ... */ format for multiline comments, put the closing */ in column 1 of the line following the comment.
        This makes it easier to see where the comment ends.
  •     If you use lines of *'s to set off sections of code, they should be the same length.
        Don't use */ to end every line inside a box, since it is difficult to keep them lined up.

  • Use braces even when the body of an if or while is only a single line.