CS 39 -- Programming Style Guide v0.1

This page describes the style in which you are to program for this class. While you may have your own chosen style for programming, it is important that you follow this guide as closely as possible. Note that any guide, including this one, will leave latitude for personal choices. In making those choices, be consistent. It is critically important that you code be easy to read and understand for another programmer. Clarity and consistency of presentation are critical, and require real work to achieve. This guide should be useful for ensuring a consistency to presentation.

Since this is the first version of this style guide, it may contain typos, inconsistencies, unspecified elements, or other errors. Please communicate any problems that you identify to me so that I can correct, expand, and otherwise modify this document.

This style guide will rely heavily on sample code:

  1. virtualMachine.hh
  2. virtualMachine.cc

These samples nearly conform to this guide. First, you should follow the guide before following the samples. Second, there is slight latitude for deviating from the guide. If you do deviate, you must do so consistently, you should provide a good reason, and I recommending not doing so any more than the samples do.


Modules and overall structure

  1. Divide your code into modules, where each module provides a distinct set of capabilities that can be used by another module.

  2. Each module should be well encapsulated, and thus portable to code other than your own. Avoid circular dependencies: If module A depends on module B, then B should not also depend on A if at all avoidable.

  3. If you are using object orientation, there must be a one-to-one correspondence between classes and modules.

  4. Within a module, divide and encapsulate your code thoroughly with functions/methods. If a common task can easily be extracted into another function/method, then do so.

  5. There must be a main module that contains only the main() function. That main() function should return int, not void. The return value should be 0 for any normal execution.

  6. Every module other than the main module must comprise both a head and a code file (see below).

  7. Use a Makefile to automatic the compilation and linking of your code. You must use the -Wall compilation to generate all compiler warnings. (Your finished code should have none.)

  8. You code should be accompanied by a README file that explains how to compile the code, how to run the resulting executable, and what limitations may exist for using the executable. Your writing must be well structured and use correct English.


Formatting

  1. Your code should be divided into segments, where each segment is a sequence of lines that serve a similar purpose. One example of a segment is a single function or method. Another example of a segment is the set of #include directives.

  2. Each segment of the code should be surrounded by divider comment lines -- those comment lines that contain only a sequence of dash (-) characters.

  3. The segments should follow the sequence given below for header and for code files.

  4. There should exactly three (3) blank lines between each segment.

  5. Within the body of a function, method, structure, or class definition, tightly associated lines should be grouped together, with no blank lines inbetween. There should be exactly one (1) blank line between these tightly associated groups of lines.

  6. There must be a space on either side of any operator (that is, +, -, ==, etc.).

  7. Declare only one variable per line.

  8. When declaring a pointer, the asterisk (*) must immediately follow the type that it modifies (no spaces inbetween). There must be a space following the asterisk, before the variable name is given.

  9. No space should separate a type cast from the variable or expression that it modifies.

  10. For control structures (e.g. if, for, while, etc.), a space should separate the keyword from the parenthesized conditional expression. A space should then separate that conditional expression from opening and closing braces ({, }).

  11. All control structure bodies must be enclosed in braces, even if the body comprises only a single statement. A blank line must separate each brace from its enclosed statements.

  12. Enclosing braces must not be on the same line as a statement contained by those braces.

  13. A function/method call should not have a space separating the name from the parenthesized argument list.

  14. No line of code should be longer than 72 characters unless absolutely unavoidable. (Note that (X)Emacs wrapping occurs at 72 characters. Use M-x column-number-mode to see the width of your lines.)

  15. Parameter and argument lists with more than one element should have no space before each comma, and one space after each comma.

  16. If a parameter or argument list does not fit on a single, 72-character line, then it should be divided into multiple lines where exactly one (1) parameter/argument appears per line.

  17. Expressions that do not fit on a single, 72-character line should be divided into multiple lines such that:

    1. For assignments, the line break immediately follows the assignment operator (=).
    2. The expression is divided consistently at the least precedent operator. That is, a sequence of a subexpressions being added should be divided into lines such that line breaks follow each plus operator (+).
  18. Avoid complex, compound expressions. Name local variables to store partial results from subexpressions, and then use those local variables in the larger expression, thus separating complex expression into multiple lines.

  19. The default (X)Emacs indentation must be used.


Naming

  1. Names must by default be descriptive and must not be abbreviated. (Itt is often difficult to select names, and it should be, given that you are trying to encapsulate substantial meaning such a short representation.) The following exceptions may be applied to this rule:

    1. The name would be so long as to interfere with clear formatting and presentation. Abbreviate in this case.
    2. Extremely common symbols may be used where their meaning can clearly be assumed. For example, the use of x and y to store cartesian coordinates would be acceptable.
  2. Class names must be capitalized. No other names may be capitalized.

  3. Type names must include the suffix _t.

  4. Structure names must include the suffix _s.

  5. When using object orientation, data member names must include an underscore (_) as a prefix.

  6. Names composed of multiple words should combine those words in one the two following formats. Do not mix these two formats -- select one and use it everywhere:

    1. No spaces between words. All words except the first are capitalized. For example, quickBrownFox.
    2. Each word is separated by an underscore (_). None of the words are capitalized. For example, quick_brown_fox.

Commenting

  1. Do not use the C-style (/* */) comment delimiters. Use only the C++-style (//) comment leader.

  2. Each group of lines of code should be commented, even if the task being performed by those lines is simple.

  3. Each function/method should be preceeded by a comment that describes that function/method.

  4. Comments should be descriptive and written in proper English. When a short phrase, rather than a whole sentence, can clearly communicate the purpose of the comment, then you may use that short phrase.

  5. Comments must always be placed on lines that preceed the code to which they refer.

  6. All elements of your code must be commented, including constants and #include statements.


Header file specifics

  1. Each header file must contain the following segments in the following order:

    1. Description
    2. Multiple inclusion beginning (see below)
    3. #include directives (if any)
    4. Constants that do not depend on types/structures/classes defined and exported by this module (if any)
    5. Types, structure, and class definitions to be exported from by module (if any)
    6. Constants that do depend on the types/structures/classes defined above
    7. Function declarations (if any)
    8. Multiple inclusion ending (see below)
  2. Multiple inclusion must be avoided using pre-processor directives. The beginning and ending segment of each header file should follow exactly the formatting and naming convention showed in example header file.

  3. The parameter lists of function and method prototypes (that is, the declared function/method without its body) must indicate not only types but also names.

  4. For class definitions, the public paragraph must be presented first, and private or protected paragraphs later.

  5. All function and method prototypes must be throughly commented, forming a kind of documentation for the use of that module.


Code file specifics

  1. Each code file must contain the following segments in the following order:

    1. Description
    2. #include directives (if any)
    3. Constants that do not depend on types/structures/classes defined in this file (if any)
    4. Types, structure, and class definitions used only in this file (if any)
    5. Constants that do depend on the types/structures/classes defined above (if any)
    6. Forward function declarations (if any)
    7. One segment per function or method defined (if any)
  2. When defining a function or method:

    1. The return type and other modifiers (e.g. static, inline) must appear alone on the first line of the signature. The name and parameters must be given on subsequent lines.
    2. A space must separate the name from the opening parenthesis (().
    3. Another space should separate the closing parenthesis ()) from the opening brace ({).
  3. Functions and methods should be ordered from lowest to highest level. That is, the most high-level functions/methods that call other functions/methods in the module should be last. The lowest-level functions/methods that do not call others in the module should be first.


Scott F. Kaplan
Last modified: Sat Sep 27 13:43:13 EDT 2003