R.Ø.S.A. Coding Style Guide

By Марко Николић а.к.а. Маркони | June 12, 2000

Abstract Link to heading

This is draft of coding style guide to be used by R.Ø.S.A. It is general purpose coding style guide and it will be accompanied by set of language specific style guides that can further specify style or even overwrite some standards set in this document for some specific language. It should be without modifications applicable to C, C++, java, javascript, php and tcl.

Introduction Link to heading

This document describes the coding standards we’d like to have for all of R.Ø.S.A. code. It has rules for both formatting and content, together with occasional rationale (or rationalization) for those rules. Although you may disagree with many of the decisions made here, please try to swallow your indignation and conform to these standards. It is very important that everyone can read and understand the software, so uniformity is a goal.

Many of the style choices here are mandatory, but don’t follow them blindly if you are changing existing code. When changing existing code it is better to conform to the style (indentation, spacing, commenting, naming conventions) of the existing code. Mixed coding style is harder to maintain than bad coding style.

Lastly, like rules of etiquette, these guidelines are not an end in themselves, but rather they attempt to move you to be mindful of your actions, for they are not private - they affect others (future readers and maintainers).

File Structure Link to heading

Each source code file should either contain

  • an entire application
  • set of related procedures that make up a package
  • configuration options

The source code file must start with part referred to as header. It is a comment that contains overall information about the file as a whole. It must contain:

  • Name of the file.
  • Author(s).
  • Brief description of the overall functions provided by the file.
  • Copyright notice.
  • Revision history.

After the file header, you may include other files or state requirements of this file.

Then you may declare and document global variables and data structures.

Every procedure (or function) should begin with a procedure header. It is a comment that gives overall documentation for the procedure. It must contain:

  • Name of the procedure.
  • Author(s).
  • Brief description of what procedure does.
  • Names, types and descriptions of arguments.
  • Results - describe the type and the value that is returned
  • Exceptions that procedure may throw.

Procedure header may also contain conditions that should be met before procedure is called, what conditions are met after the procedure is succesfully finished and list of packages that use this procedure.

After procedure header you should declare and document all of your local variables. If language permits you to, you can declare some variables later, but only if they scope is very limited (couple of lines). Documentation should state purpose of variable.

Comments Link to heading

Beside comments that we already described (file header, description of data structures and global variables, procedure headers and description of local variables) you shouldn’t have to use comments too much. If the code is clear and uses good names it should explain itself. Too much comments make the code unreadable, so don’t try to impress someone with your ability to create dummy comments that are obvious from the code itself.

The opening / of all comments should be indented to the same level as the code to which it applies, for example:

if (foo()) {
	/*
	 * Explanation of following code.
	 */
	...
}

Here is example of how comments should look (except for the tcl which unfortunately doesn’t have multiline comments):

/* single line comments look like this */

/*
 * Multiline comments look like this.  Put the opening and closing
 * comment sequences on lines by themselves.  Use complete sentences
 * with proper English grammar, capitalization, and punctuation.
 */

/*
 * Important single line comments look like multi-line comments.
 */

/* but you don't need to punctuate or capitalize one-liners */

Boolean values Link to heading

For languages that don’t have Boolean type, use 1 for true and 0 for false. If possible and convinient, define constants ’true’ and ‘false’ to hold appropriate Boolean values.

Naming conventions Link to heading

Names should be meaningful in the application domain, not the implementation domain. This makes your code clearer to a reader who is familiar with the problem you’re trying to solve, but is not familiar with your particular way of solving it. Also, you may want the implementation to change some day. Note that well-structured code is layered internally, so your implementation domain is also the application domain for lower levels.

Names should be chosen to make sense when your program is read. Thus, all names should be parts of speech (English, of course) which will make sense when used with the language’s syntactic keywords. Variables should be noun clauses. Boolean variables should be named for the meaning of their “true” value. Procedures should be named for what they do, not how they do it. Function names should reflect what they return, and boolean-valued functions of an object should be named for the property their true value implies about the object. Functions are used in expressions, often in things like if’s, so they need to read appropriately. For instance,

if (checksize(x))

is unhelpful because we can’t deduce whether checkSize returns true on error or non-error; instead

if (validsize(x))

makes the point clear and makes a future mistake in using the routine less likely. Longer names contain more information than short names, but extract a price in readability. Compare the following examples:

for (elementindex = 0; elementindex < DIMENSION; elementindex++)
	elements[elementindex] = 0;

for (i = 0; i < DIMENSION; ++i)
	elements[i] = 0;

In the first example, you have to read more text before you can recognize the for-loop idiom, and then you have to do still more hard work to parse the loop body. Since clarity is our goal, a name should contain only the information that it has to.

Carrying information in a name is unnecessary if the declaration and use of that name is constrained within a small scope. Local variables are usually being used to hold intermediate values or control information for some computation, and as such have little importance in themselves. For example, for array indices names like i, j, and k are not just acceptable, they are desirable.

Similarly, a global variable named x would be just as inappropriate as a local variable named elementIndex. By definition, a global variable is used in more than one function or module, so all of it’s uses will not be visible at once. The name has to explain the use of the variable on its own. Nevertheless there is still a readability penalty for long names: casefold is better than case_fold_flag_set_by_main.

In short, follow “Mike’s Rule” to make variable name size proportional to scope:

length(name(variable)) ~ log(countlines(scope(variable)))

Avoid ‘Hungarian’-style naming conventions which encode type information in variable names. They may be systematic, but they’ll screw you if you ever need to change the type of a variable. If the variable has a small scope, the type will be visible in the declaration, so the annotation is useless clutter. If the variable has a large scope, the code should modular against a change in the variable’s type. In general, any deterministic algorithm for producing variable names will have the same effect.

All variable, functions and procedure names should start with lowercase letter. Constant variables should be all uppercase.

We will not set standard here for multi-word names, because we believe that it is best to use convention for names that is consistent with the language standard library.

Indentation Link to heading

We will follow this basic layout:

control {
	statement;
	statement;
}

if (expr) {
	statement;
} else if (expr) {
	statement;
} else if (expr) {
	statement;
} else {
	statement;
}

switch (expr) {
case ABC:
case DEF:
	statement;
	break;

case UVW:
	statement;
	/* FALLTHROUGH */

case XYZ:
	statement;
	break;
}

Line Continuation Link to heading

You should use continuation lines to make sure that no single line exceeds 80 characters in length. Countinuation lines should be indented one tab. If control statement should be split, then open curly brace should be on line by itself on same indentation level as control statement. Try to start each continuation line with an operator such as && or || - this makes it clear that the line is a continuation, since new statement would never start with such an operator.

if (foo->next == NULL && totalcount < needed && needed <= MAX_ALLOT && server_active(current_input)) {
	...
}

if (foo->next == NULL
	&& totalcount < needed && needed <= MAX_ALLOT
	&& server_active(current_input))
{
	...
}

Spacing Link to heading

Binary operators must be surrounded by one whitespace and unary operators should be glued with expression (if language syntax permits it).

var x = 0;

for (i = 0; i < 10; i++) {
	statement;
}

if (!x) {
	statement;
}

Example File Link to heading

TODO: insert some good example of proposed coding standard here.

  1. Style Guide for Tcl Scripts
  2. Notes on Programming in C
  3. Standards and Style for Coding in ANSI C
  4. Recommended C Style and Coding Standards

Revision History Link to heading

Document Revision # Action Taken, Notes When? By Whom?
0.2 Modified 12/06/2000 Marko Nikolic
0.1 Creation 12/05/2000 Marko Nikolic