Computer Engineering 130
File Processing
Contents

 


Navigation

CmpE130 Lab Documentation

 

Design Report Format

The design report should be structured in numbered sections 1-7. Each section should be divided into numbered subsections 1.1, 1.2, etc. as required. The structure for doing this is not specified. However, the contents required in each section are specified. You may find that adding other sections may make your discussion clearer.


Source Code Standard

Contents:

Sources:

This documentation standard is derived from some previously existing standards:

Firmware Standards Manual found at http://www.ganssle.com/misc/fsm.doc
Documentation Format found at
http://www.cs.wpi.edu/Help/documentation-standard.html
C# Coding Style Guide found at
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=336

Motivation:

The motivation for this standard is that its adoption should:

Modules

General

A Module is a single file of source code that contains one or more functions or routines, as well as the variables needed to support the functions.

Each module contains a number of related functions. For instance, an A/D converter module may include all A/D drivers in a single file. Grouping functions in this manner makes it easier to find relevant sections of code, and allows more effective encapsulation.

Encapsulation — hiding the details of a function's operation, and keeping the variables used by the function local — is absolutely essential.

Modules tend to grow large enough that they are unmanageable. Keep module sizes under 1000 lines to insure tools (source debuggers, compilers, etc.) are not stressed to the point they become slow or unreliable, and to ease searching.

Templates

To encourage a uniform module look and feel, create module templates. Use one of these files as the base for all new modules. The module template includes a standardized form for the header (the comment block preceding all code), a standard spot for file includes and module-wide declarations, function prototypes and macros. The templates also include the standard format for functions.

Header Template

Documentation Sample

Variables

Names

Regardless of language, use long names to clearly specify the variable's meaning. If your tools do not support long names, get new tools.

Separate words within the variables by underscores. Do not use capital letters as separators. Consider how much harder IcantReadThis is on the eyes versus I_can_read_this.

The ANSI C specification restricts the use of names that begin with an underscore and either an uppercase letter or another underscore (_[A-Z_][0-9A-Za-z_]). Much compiler runtime code also starts with leading underscores. To avoid confusion, never name a variable or function with a leading underscore.

These names are also reserved by ANSI for its future expansion:

E[0-9A-Z][0-9A-Za-z]*     errno values
is[a-z][0-9A-Za-z]*     Character classification
to[a-z][0-9A-Za-z]*     Character manipulation
LC_[0-9A-Za-z_]*     Locale
SIG[_A-Z][0-9A-Za-z_]*     Signals
str[a-z][0-9A-Za-z_]*     String manipulation
mem[a-z][0-9A-Za-z_]*     Memory manipulation
wcs[a-z][0-9A-Za-z_]*     Wide character manipulation

Global Variables

All too often C++ and especially assembly programs have one huge module with all of the variable definitions. Though it may seem nice to organize variables in a common spot, the peril is these are all then global in scope. Global variables are responsible for much undebuggable code, reentrancy problems, global warming and male pattern baldness. Avoid them!

When globals are used, put all of them into a single module. They are so problematic that it's best to clearly identify the sin via the name globals.c or globals.asm.

Declarations

Number of Declarations per Line

One declaration per line is recommended since it encourages commenting. In other words,

int level; // indentation level
int size; // size of table

Do not put more than one variable or variables of different types on the same line when declaring them. Example:

int a, b; //    What is 'a'? What does 'b' stand for?

The above example also demonstrates the drawbacks of non-obvious variable names. Be clear when naming variables.

Initialization

Try to initialize local variables as soon as they are declared. For example:

string sname = myObject.Name;

or

int val = time.Hours;

Functions

Regardless of language, keep functions small! The ideal size is less than a page; in no case should a function ever exceed two pages. Break large functions into several smaller ones.

Explicitly declare every parameter passed to each function. Clearly document the meaning of the parameter in the comments.

Define a prototype for every called function, with the exception of those in the compiler's library. Prototypes let the compiler catch the all-too-common errors of incorrect argument types and improper numbers of arguments. They are cheap insurance.

Preconditions and postconditions should be explicitly described.

In general, function names should follow the variable naming protocol. Remember that functions are the "verbs" in programs — they do things. Incorporate the concept of "action words" into the variables' names. For example, use read_A/D instead of A/D_data, or send_to_LCD instead of LCD_out.

Comments

Code implements an algorithm; the comments communicate the code's operation to yourself and others. Adequate comments allow you to understand the system's operation without having to read the code itself.

Write comments in clear English. Use the sentence structure Miss Grandel tried to pound into your head in grade school. Avoid writing the "Great American Novel"; be concise yet explicit… but be complete.

Avoid long paragraphs. Use simple sentences: noun, verb, object. Use active voice: "Start_motor actuates the induction relay after a 4 second pause". Be complete. Good comments capture everything important about the problem at hand.

Use proper case. Using all caps or all lower case simply makes the comments harder to read.

Enter comments in C++ at block resolution and when necessary to clarify a line. Don't feel compelled to comment each line. It is much more natural to comment groups of lines which work together to perform a macro function. However, never assume that long variable names create "self documenting code". Self documenting code is an oxymoron, so add comments where needed to make the firmware's operation crystal clear. It should be possible to get a sense of the system's operation by reading only the comments.

Comment any line that is not crystal clear. There is no need to comment the obvious such as:


a++; // increases the counter
return; // returns from the subroutine

Such comments are a) an insult to your reader's intelligence and b) tedious to write.

Explain the meaning and function of every variable declaration. Every single one. Explain the return value, if any. Long variable names are merely an aid to understanding; accompany the descriptive name with a deep, meaningful, prose description. Explain the parameters during the function definition, as follows:

type function_name(type parameter1 /* comment */
                   type parameter2 /* comment */)

Though it's useful to highlight sections of comments with strings of asterisks, never have characters on the right side of a block of comments. It's too much trouble to maintain proper spacing as the comments later change. In other words, this is not allowed:

/************************************************
* This comment incorrectly uses right-hand *
* asterisks *
************************************************/

The correct form is:
/************************************************
* This comment does not use right-hand
* asterisks
*************************************************/

Single line comments must be indented to the indent level when they are used for code documentation. Commented out code should be commented out in the first line to enhance the visibility of commented out code.

A rule of thumb says that generally, the length of a comment should not exceed the length of the code explained by too much, as this is an indication of too complicated, potentially buggy, code.

Coding Conventions

General

No line may ever be more than 80 characters.

Never, ever use "magic numbers". Instead, first understand where the number comes from, then define it in a constant, and then document your understanding of the number in the constant's declaration.

Spacing and Indentation

Put a space after every keyword, unless a semicolon is the next character, but never between function names and the argument list.

Put a space after each comma in argument lists and after the semicolons separating expressions in a for statement.

Put a space before and after every binary operator (like +, -, etc.). Never put a space between a unary operator and its operand (e.g., unary minus).

Put a space before and after pointer variants (star, ampersand) in declarations. Precede pointer variants with a space, but have no following space, in expressions.

Indent C++ code using tab characters.

Always place the # in a preprocessor directive in column 1.

C++ Formatting

Never nest if statements more than three deep; deep nesting quickly becomes incomprehensible. It's better to call a function, or even better to replace complex ifs with a switch statement.

Place braces so the opening brace is the last thing on the line, and place the closing brace first, like:

if (result > a_to_d) {
   do a bunch of stuff
}

Note that the closing brace is on a line of its own, except when it is followed by a continuation of the same statement, such as:

do {
  body of the loop
} while (condition);

When an if-else statement is nested in another if statement, always put braces around the if-else to make the scope of the first if clear.

When splitting a line of code, indent the second line like this:

function (float arg1, int arg2, long arg3,
          int arg4)

or,
if (long_variable_name && constant_of_some_sort == 2
    && another_condition)

Use too many parentheses. Never let the compiler resolve precedence; explicitly declare precedence via parentheses.

Wrapping Lines

When an expression will not fit on a single line, break it up according to these general principles:

Example of breaking up function calls:

longFunctionCall(expr1, expr2,
                 expr3, expr4, expr5);

Examples of breaking an arithmetic expression:

PREFER:
var = a * b / (c - g + f) +
      4 * z;

BAD STYLE — AVOID:
var = a * b / (c - g +
      f) + 4 * z;

The first is preferred, since the break occurs outside the parenthesized expression (higher level rule). Note that you indent with tabs to the indentation level and then with spaces to the breaking position in our example this would be:

> var = a * b / (c - g + f) +
> ......4 * z;

Where '>' are tab chars and '.' are spaces. (the spaces after the tab char are the indent width of the tab). A good coding practice is to make the tab and space chars visible in the editor which is used.

White Spaces

An indentation standard using spaces never was achieved. Some people like 2 spaces, some prefer 4 and others die for 8, or even more spaces. Better use tabs. Tab characters have some advantages:

Here, we define the Tab as the standard indentation character.

Blank Lines

Blank lines improve readability. They set off blocks of code which are in themselves logically related. Two blank lines should always be used between:

One blank line should always be used between: