Coding Guidelines

Table of Contents


Introduction
Guidelines
Identifiers
Abbreviation is your enemy.
When an identifier’s name gets to be longer than 30 characters, consider renaming it.
Underscores_are_your_friends.
Avoid using two underscores in a row.
Capitalization makes identifiers even easier to read.
Avoid using all capital letters for names of constants.
Avoid including the type of the variable in its name.
Name a variable based on its usage.
If a variable has the same name as another variable in a larger scope, consider renaming the smaller scope variable.
Avoid having the only difference between two identifiers be upper versus lower case.
Whitespace
Place a space after an identifier if it is followed by an open bracket.
Do not place a space after an open bracket if it is followed by an identifier.
Do not place a space after an identifier if it is followed by an close bracket.
Do not place a space between two of the same brackets.
Place a space between a close bracket and an open bracket of the same type.
Do not place a space between an open bracket and a close bracket of the same type.
Place a space after a comma.
Place a space on both sides of a mathematical or comparison operator (including '?' and ':').
Place a space after an identifier if it is followed by an asterisk ('*').
Do not place a space after an asterisk ('*') if it is followed by an identifier.
Do not place a space after an identifier if it is followed by an ampersand ('&').
Place a space after an ampersand ('&') if it is followed by an identifier.
Never use hard tabs in your source files (have your editor insert spaces instead of tabs).
Place a space after a semicolon (';') unless it is followed by another semicolon or at the end of a line.
Do not place a space on either side of a scope resolution operator ("::").
Place a space between the word "operator" and the operator itself when writing an operator overload function.
Place a blank line between function definitions.
Do not place a space after an exclamation point ('!').
Code Formatting
Place a curly bracket on its own line and line it up vertically with the matching curly bracket.
Always indent code appearing after an open curly bracket.
If a line is wider than one screen width (this may vary depending on the editor you use), consider finding a good place to split the statement and putting it on two lines.
When using a constant in a comparison expression, always place the constant on the left side of the comparison operator.
When the difference is unimportant, always use ++prepending instead of postpending++ increment/decrement.
For a function with a large number of arguments, it is okay to declare the function with one variable on its own line.
Always place a curly bracket after an if statement, even if there is only one statement being controlled by the condition.
Always line up the 'else' keyword vertically with its matching 'if' keyword.
If an expression is long enough to require multiple lines, start the next line with an operator as opposed to leaving a 'dangling' operator at the end of the previous line.
Instead of writing something as (TRUE == (expression)), write it as (expression).
Instead of writing something as (FALSE == (expression)), write it as (!(expression)).

Always declare variables using the smallest scope possible.

Always declare a default: branch for a switch statement.
Always assign a pointer to NULL after deleting it.
If checking an expression and returning true or false based on the result, return the expression instead.
Goto statements are considered harmful.
When using an I/O stream, always use "<< endl" instead of "<< '\n'".
If you are going to typecast, use the casting operators (if available).
If the casting operators are unavailable, use the format "(type) (expression)".
Classes
When defining a class, always explicitly declare the private: section.
Always declare the protected: and public: sections, even if there is nothing in them.
When deriving one class from another class, explicitly declare the inheritance type, even if it is private.
Always overload the "friend ostream& operator <<" function and output the contents in a nice, readable format.
When overloading "operator <<", do not include leading or trailing whitespace (including endl!) in your implementation.
When defining a class, always make the header file which includes the class declaration as the first #included file.
Functions
It is acceptable to declare a function which is only called in one place.
If a function is more than 100 lines long, consider the use of sub-functions.
Always explicitly return from a function, even if it is a void function.
Always put parenthesis around the value being returned.
Try to design your functions so that they only have one return statement.
Files on Disk
A file with the extension of ".h" should generate no code or data.
A file with the extension of ".hpp" may generate code or data.
Limit the placement of one class per source file.
When a source file gets to be longer than 1000 lines, consider breaking it down into multiple source files.
Include whatever keyword is supported by your SCM system to tell you the file name, revision, author, etc. in each of your source files.
Do not put path locations (relative or absolute) in #include statements.
Never require other files to be #included before any other #include file.
Always add a mechanism to prevent getting compiler errors if an include file is #included more than once.
Summary
Glossary
angle bracket
bracket
close bracket
culled
curly bracket
open bracket
parenthesis
square bracket
tome
vernacular
 

Introduction

 

Greetings! You are about to embark on a journey which will (well, we hope that it does, anyway) change how you write code. Please note that what you are about to read in the pages of this tome is a collection of suggestions, culled from the vast experience and code, both good and bad, from the Continuation Engineering department here at NetSoft. While these guidelines will help to produce more readable and possibly more stable code, keep in mind that they are just what we say: guidelines. There may be very good reasons to not follow certain guidelines in some circumstances. Then don’t. But adhering to these as much as possible will make all of our jobs a lot easier.

"But why does it matter what it looks like? As long as it works, that’s what matters." When you are writing a piece of software, you are actually writing for two different audiences. Yes, one of them is the end user. Give yourself a pat on the back for that one. The other one isn’t always that obvious. But it happens to be you. It also happens to be us. That’s right. It is whoever has to look at the code for enhancements, maintenance, debugging, or trying to figure out what your code is doing. It is also why we use punctuation and paragraphs in writing. It presents the information in a readable, easy-to-understand format which is familiar to you.

Here is how this document works: There are several major categories which will contain one or more recommendation. For each recommendation, an example will be provided showing the context of the recommendation. When a valid exception exists, it will also be shown in the example. As well as a functional example, a reason for doing it this way versus another will be provided.

Instead of making another dull document you have to suffer your way through, we tried to make this document fun to read. Through the use of humor, we are by no means negating the importance of one guideline versus another. Also, while reading, please remember that we are all human, and thereby prone to making errors. Please don’t ridicule any bad grammar, spelling, or failed attempts at jokes. Thank you.

 


Guidelines


Identifiers

"So," you say, "just what do you mean by the word ‘identifier’?" Fair enough. Everyone has a certain vernacular they are used to using, and you may not be familiar with a concept based on the words we use. For the purposes of this document, the word "identifier" means "any token which is used to refer to a variable, function, class, type, etc." In other words, it’s what name you give to something. With that all said and done, let’s start!

 

Abbreviation is your enemy.

Despite what you may think, abbreviations are not always easy to understand. As well as being taxing on the person trying to read the code, it is sometimes a headache for the person writing the code. "But wait," you’re thinking (you are, I can just tell). "The reason that I make something abbreviated is to make it easier on me." Most of the time, this is a true statement. However, and I know that this has happened to me on more than one occasion, sometimes you can’t remember exactly how you abbreviated this one word. Now you have to go and find either another call into it, or the definition itself. I believe that it is some derivation of Murphy’s Law which states "If you don’t remember the abbreviation the first time, you are doomed to a lifetime of looking it up."

Example:

char ChrFrmUsr;                 // Poor!
char Character_From_User;       // Great!

void GetVal (void);             // Get valid? Value?
void Get_Valium (void);         // Oh. I see now.

When an identifier’s name gets to be longer than 30 characters, consider renaming it.

Please note that in this document, we are using descriptive identifier names, not long ones. The fact that some of them are more than 15 characters derives from the fact that they are descriptive. Some problems with identifier names which are too long are:

Example:

char Character_Inputted_By_User_From_Keyboard;  // Whoa!  Bad!
char Character_From_User;                       // Manageable, yet descriptive.

 

Underscores_are_your_friends.

When naming identifiers, it is difficult to read names where the words are all mashed together. In order to make understanding what a variable is used for better, it is easiest to use a descriptive name, which may consist of multiple words.

Example:

char characterfromuser;         // Could stand improvement...
char CharacterFromUser;         // Better...
char character_from_user;       // Better yet...
char Character_From_User;       // Excellent!

 

Avoid using two underscores in a row.

The negative side to using an identifier with two consecutive underscores in it is that it is difficult to distinguish between a single underscore versus two underscores in a row, especially in a proportional font.

Example:

char Car__Color;        // Difficult to notice as two vs. one underscore.

 

Capitalization makes identifiers even easier to read.

As well as being descriptive it is important that an identifier be easy to read. The underscores between the individual words makes them a lot easier to read, and adding the capitalization makes them easier still.

Example:

char characterfromuser;         // Could stand improvement...
char CharacterFromUser;         // Better...
char Character_From_User;       // Excellent!

 

Avoid using all capital letters for names of constants.

Aside from being difficult to read, making the name of a constant in all capital letters is another maintenance hassle. "But constants don’t change," you interject. Sure they do. They change into variables. When that does happen, converting all the references to mixed case is enough to give you mixed emotions about having done the change. But if you don’t, you have inconsistent code.

Example:

// Falling Speed Calculator 1.0
const float GRAVITY = 9.8;      // Yep, it doesn't change.
const float Gravity = 9.8;      // Easier to read, and portable...

 

Avoid including the type of the variable in its name.

Although this notation is particularly popular among Windows programming , Hungarian notation is not all the good it is cracked up to be. "But by knowing the data type," you’re thinking, "then I will be able to make sure that I am passing the correct data types to a function." This is a true statement, to some effect. But what happens when you change the type of a certain variable? You have to change its name. If you don’t, then you are worse off than as if you didn’t even have the type in there in the first place. All you are creating are future maintenance headaches. Also, as far as the type checking portion of it goes, the compiler will tell you if you are passing the wrong type to a function.

Example:

char *lpszName;         // What're you talking about, Willis?
char *Name;             // That's much better.

 

Name a variable based on its usage.

It is much easier to read code if the variable names come close to matching the use of the variable. Variable names such as j, k, hotdog, Int, etc. are all bad. If a variable is used for loop control, name it Index or Loop. This will help even if you are referencing the variable while not in its loop, because it will be easier to see where it came from.

Example:

void *nptX;                             // Very poor nmaing choice.
void *Emulator_Buffer;                  // Now we know what we're looking at
                                        // here.

for (int j = 0; j != 10; ++j)           // If this is reference elsewhere (such
                                        // as inside the loop) it may not be
                                        // obvious where it came from.
for (int Loop = 0; Loop != 10; ++Loop)  // Now we know where to look based on
                                        // the name only!

 

If a variable has the same name as another variable in a larger scope, consider renaming the smaller scope variable.

The main reason for this guideline is to stop simple errors from happening. The errors, which may be caused by violating this guideline, are difficult to find, because the compiler does not error on them. See the example for one of the most common errors you may receive.

Example:

char *Name;

{
  char *Name = new char [100];

  strcpy (Name, "Name unknown");
}

cout << name; // uh-oh! this will output junk, not // to mention that now we have a memory // leak, too! 

 

Avoid having the only difference between two identifiers be upper versus lower case.

The negative of this is that if you are not paying very careful attention to what you are doing, you may end up using the incorrect variable.

Example:

int Line_Length;                        // Good!
int line_length;                        // Accidentally forget to capitalize the
                                        // name and now you won't get a compiler
                                        // error, just a headache and/or incident!

Whitespace

Before we go diving off telling you where you should and should not be putting whitespace, there are a couple of terms we would like to define. Please click on each of the terms following to make sure you understand what we mean by each of them:

bracket
open bracket
close bracket
round bracket (more commonly known as parenthesis)
angle bracket
curly bracket
square bracket

 

Instead of giving reasons for each of these guidelines, examples will merely be provided. The reason for all of the guidelines are the same: to provide consistency in the formatting of the code and make it easier to read.

 

Place a space after an identifier if it is followed by an open bracket.

void My_Function(void);                 // Yuck.
void My_Function (void);                // Preferred.

 

Do not place a space after an open bracket if it is followed by an identifier.

Do not place a space after an identifier if it is followed by an close bracket.

void My_Function ( void );              // Yuck.
void My_Function (void);                // Preferred.

 

Do not place a space between two of the same brackets.

void My_Function ( (Variable1 + 5) * (Variable2 + 3) );  // Yuck.
void My_Function ((Variable1 + 5) * (Variable2 + 3));    // Preferred.

 

Place a space between a close bracket and an open bracket of the same type.

void My_Function (My_Array [1][2]);     // Yuck.
void My_Function (My_Array [1] [2]);    // Preferred.

 

Do not place a space between an open bracket and a close bracket of the same type.

delete [ ] Variable;                    // Yuck.
delete [] Variable;                     // Preferred.

 

Place a space after a comma.

My_Function (Variable1,Variable2);      // Yuck.
My_Function (Variable1, Variable2);     // Preferred.

 

Place a space on both sides of a mathematical or comparison operator (including '?' and ':').

Variable1=(Variable2+5);                // Yuck.
Variable = (Variable2 + 5);             // Preferred.

 

Place a space after an identifier if it is followed by an asterisk ('*').

Do not place a space after an asterisk ('*') if it is followed by an identifier.

This guideline specifically excludes the use of the asterisk as a multiplication identifier.

char*My_String;                         // Yuck.
char* My_String;                        // Also Yuck.
char * My_String;                       // Still Yuck.
char *My_String;                        // Preferred.

 

Do not place a space after an identifier if it is followed by an ampersand ('&').

Place a space after an ampersand ('&') if it is followed by an identifier.

This guideline specifically excludes the use of the asterisk as an address identifier.

char&My_String;                         // Yuck.
char &My_String;                        // Also Yuck.
char & My_String;                       // Still Yuck.
char& My_String;                        // Preferred.

 

Never use hard tabs in your source files (have your editor insert spaces instead of tabs).

This guideline is especially important. The use of hard tab characters ends up causing problems because not every editor uses the same number of spaces per tab character (in fact, most editors allow you to configure how many spaces there are per tab character). If you open a file with hard tabs already in it, instead of modifying the code so that it is readable in your own editor because your tab stops are different, please remove the tabs. There are several utilities which will do this. If you are in need of one of these utilities, contact Continuation Engineering for assistance. There is no example for this guideline.

 

Place a space after a semicolon (';') unless it is followed by another semicolon or at the end of a line.

for (i=1;i!=10;++i)                     // Yuck.
for (i = 1; i != 10; ++i)               // Preferred.
for (;;)                                // Also acceptable.

 

Do not place a space on either side of a scope resolution operator ("::").

void My_Class :: Method (void)          // Yuck.
void My_Class::Method (void)            // Preferred.

 

Place a space between the word "operator" and the operator itself when writing an operator overload function.

My_Class operator= (My_Class);          // Yuck.
My_Class operator = (My_Class);         // Preferred.

 

Place a blank line between function definitions.

This guideline is to make it easier to find multiple function definitions in one source file. There is no example for this guideline.

 

Do not place a space after an exclamation point ('!').

if (! My_Pointer)                       // Yuck.
if (!My_Pointer)                        // Preferred.

Code Formatting

Code is much easier to read and understand if it is formatted well. The following guidelines merely deal with the placement of certain characters in relationship to identifiers or just in the code itself.

 

Place a curly bracket on its own line and line it up vertically with the matching curly bracket.

Being able to find a curly bracket is very important to resolve scope of local variables. For this reason, it is easiest to find a curly bracket if it is placed on its own line. The one valid exception to this rule is when you are defining an empty function, at which point it would be acceptable to place both the opening and closing curly bracket on the same line as each other.

Example:

if (1 == My_Variable) {                 // Yuck.
  My_Function ();
}

if (1 == My_Variable)                   // Much better!
{
  My_Function ();
}

 

Always indent code appearing after an open curly bracket.

As well as having the open and close curly brackets line up, if the code is indented inside the curly brackets it will make the vertical alignment of code more obvious as to what each lexical level is attempting to do.

Example:

if (1 == My_Variable) {                 // Yuck.
  My_Function ();
}

if (1 == My_Variable)                   // Much better!
{
  My_Function ();
}

 

If a line is wider than one screen width (this may vary depending on the editor you use), consider finding a good place to split the statement and putting it on two lines.

It is very difficult to read code which runs off the right end of your visible display. Another aggravating part of having long lines in your code is that they very rarely print out properly. However, there may be times at which it may not be appropriate to split the statement into two lines, and that is acceptable. There is no example for this guideline.

 

When using a constant in a comparison expression, always place the constant on the left side of the comparison operator.

The primary benefit from always doing this is that if you accidentally only use one equals sign in your is-equal-to comparison, you will get a compiler error, because you cannot assign a value into a constant.

Example:

if (Unlucky_Number == 13)               // Could be a problem if you only put
                                        // one equal sign on accident!
if (13 == Unlucky_Number)               // Much better, and doesn't lose any
                                        // readability.

 

When the difference is unimportant, always use ++prepending instead of postpending++ increment/decrement.

While this doesn't greatly affect the readability of the code, this does increase the efficiency of the compiler, as it may sometimes have to evaluate the use of a value going to be incremented in a loop to determine whether or not the increment has already taken place. With prepending increment, the compiler knows that the incrementing of the variable is one of the first things it should do.

Example:

My_Variable++;                          // Okay...
++My_Variable;                          // Much better!

 

For a function with a large number of arguments, it is okay to declare the function with one variable on its own line.

This is related to the reason why you should split up exceptionally long lines in your editor. This make the code easier to read, not only for when you print it out, but it is easier to find the breaks between each of the variables being passed to the function. Also, you have the benefit of being able to comment on each of the parameters with the use of the // end of line comment identifiers. There is no example for this guideline.

 

Always place a curly bracket after an if statement, even if there is only one statement being controlled by the condition.

It is much easier to see what the intent of an if/else statement is if the controlled statements are enclosed in curly brackets. Also, this will help to prevent the accidental error of thinking that you are adding a second controlled statement when you actually aren't. There is no example for this guideline.

 

Always line up the 'else' keyword vertically with its matching 'if' keyword.

By matching the starting column of an 'else' keyword with its sibling 'if', it is much easier to find which conditional statement it is related to. There is no example for this guideline.

 

If an expression is long enough to require multiple lines, start the next line with an operator as opposed to leaving a 'dangling' operator at the end of the previous line.

This makes it easier to see what the scope is for what the current line (although it is an incomplete portion of the entire statement) is doing.

Example:

My_Variable = (Some_Function () +       // Not what we're looking for!
               Another_Function () +
               Another_Variable);
My_Variable = (Some_Function ()         // Much better!
            + Another_Function ()
            + Another_Variable);

 

Instead of writing something as (TRUE == (expression)), write it as (expression).

It is redundant to compare the value of an expression against true since that is, by definition, what an expression returns: either true or false. As well as redundant, it makes the code more wordy, and thereby a little less easy to understand.

Example:

if (TRUE == Some_Function ())           // Technically correct, but harder to
                                        // read than:
if (Some_Function ())                   // Much easier on the eyes!

 

Instead of writing something as (FALSE == (expression)), write it as (!(expression)).

It is redundant to compare the value of an expression against false since that is, by definition, what an expression returns: either true or false. As well as redundant, it makes the code more wordy, and thereby a little less easy to understand.

Example:

if (FALSE == Some_Function ())          // Technically correct, but harder to
                                        // read than:
if (!(Some_Function ()))                // Much easier on the eyes!

 

Use the const declaration in preference to #define.

While there is nothing wrong with the use of preprocessor statements, the compiler will not allow you to pass a const to a non-const receiving function, thereby providing a little bit of extended type checking in your code.

Example:

#define Pi = 3.1415926539;              // Okay, but...
const float Pi = 3.1415926539;          // This is much better!

 

Declaring iterators for a loop inside the for (;;) statement is okay.

If you are going to use an existing variable in your function, this is okay as well. However, if the only use of your variable is going to be inside this one loop, it is acceptable to declare the iterator variable inside the for statement. However, be aware that most compilers place the iterator on the scope of the outside of the loop and that redeclaring an iterator in a second loop will cause problems.

Example:

for (int Counter = 1; Counter != 10; ++Counter) // Looks good from here!

 

Instead of checking a pointer as valid with "(NULL != pointer)", check it as "(pointer)".

The use of the keyword NULL in this comparison is redundant. If you just check a pointer variable as an expression, it will return false if the pointer is NULL (because the NULL constant is declared as all zeros).

Example:

if (NULL != My_Pointer)                 // Okay, but...
if (My_Pointer)                         // ..this is much better!

 

Instead of checking a pointer as null with "(NULL == pointer)", check it as "(!(pointer))"

A pointer, when NULL, can be used in an expression to check its value. If you are checking a NULL pointer in an expression, the expression will return as a value of false. Therefore, if you want to make sure that pointer is equal to NULL, then comparing the logical not against it will return true only if the pointer is null, otherwise it will return a false.

Example:

if (NULL == My_Pointer)                  // Okay, but...
if (!(My_Pointer))                      // ...this is much better!

 

Use parenthesis to enforce the order of operations.

The order of operations in which something is performed may not always be what is expected. Unless you explicitly use parenthesis to tell the compiler what you want done in which order, the results may be somewhat less than optimal.

Example:

My_Int = (1 + 5 * 3 * 4 / 6);           // Any guesses?
My_Int = (1 + (5 * ((3 * 4) / 6)));     // Oh!  That's what you wanted!

 

Do not use /* and */ for comments inside of code. Use // instead.

The primary reason that you do not want to have /* */ comments in the middle of your code is that the compiler does not allow the nesting of comments. With this in mind, if you want to comment out a code block, if there are /* */ blocks in the middle of your code, you can't just go to the beginning of a function, type a /* and then go to the end of the function and type */ to comment the whole thing out. Instead, you would probably be best off putting a // at the beginning of each line, which takes a lot more time, especially if you are commenting out large blocks or multiple functions.

Example:

My_Variable = 10; /* for future reference */    // Okay, but...
My_Variable = 10; // for future reference       // ...this is much better!

 

Declare the type for every variable you declare.

This is another maintenance issue. While it may seem to be easier to read if you lump all the variables of a like kind together, it is in fact much simpler for maintenance if you use the variable type in its declaration. One reason is that most search programs (such as Grep) do not allow you to view surrounding lines, and even those that do would be inappropriate for use in that manner just to find out a variable type. A second reason is that if you have a bunch of variables all declared as ints, and you need to change one of them to an unsigned int, you have to move it out of the list, change its ending , to a ;, and declare the type in front of it. Wouldn't it be much easier to just add the word unsigned in front of the variable you wanted to change? Finally, another reason it is easier to declare the type for each variable is that if you are going to cut and paste a certain code section, it would be easier to go ahead and just cut and paste the variables that you need instead of having to cut out the whole section, and then remove the variables from the list which you are not going to be using in your new destination. There is no example for this guideline.

 

Instead of hardcoding a number, create a constant and use the constant instead.

If you are using the same constant value in 2 different places, this becomes exceptionally important. Yes, gravity is always 9.8 m/s/s at sea level. On Earth, anyway. Putting in 9.8 several places in your code is okay, unless you plan on accounting for altitude, or a different planet. I would much rather change the value of one constant and recompile as opposed to searching for every occurrence of 9.8 and replacing all the appropriate ones. Wouldn't you? (Exception: When you are using the values of 10 and 16 in the context of hex<->decimal conversion, the use of the numbers is vital over the use of a constant). There is no example for this guideline.

 

Try to avoid having unspecified parameter lists (...).

An unspecified parameter list is a bug waiting to crash your program. You can overload functions with C++, so there is no reason to not just declare a different version of the function for each of your parameter lists. While this may seem like a little bit more overhead, if you reuse the code properly, it should not only be equally efficient, but much easier to find while doing maintenance. There is no example for this guideline.

 

Always declare variables using the smallest scope possible.

If there isn't a need for a variable to exist somewhere, then why even have it? The same thing is true for inside a function. If you have a variable which is being used only inside of a loop, don't make it a local variable to the function. Declare it inside the loop's braces. That is where it belongs. There is no example for this guideline.

 

Always declare a default: branch for a switch statement.

If you have a default: place to go, then you will have exception handling. Don't think "Well, this will never have any value that I haven't already covered". Make your default branch the place where you do your error trapping. That will help you find a bug much faster than running through it with your debugger. There is no example for this guideline.

 

Always assign a pointer to NULL after deleting it.

This will prevent the accidental attempted use of a pointer later on (provided that there are adequate checks in the code), and also prevents you from accidentally trying to delete the same pointer twice (if you pass a NULL pointer to delete, it is designed to do nothing and return without error). There is no example for this guideline.

 

If checking an expression and returning true or false based on the result, return the expression instead.

This will save a lot of space, and make the code much more readable. Please look at the example for a visual explanation.

Example:

if (My_Variable == Another_Variable)
{
  return (TRUE);
}
else
{
  return (FALSE);
}                                       // Easy to understand, but a little
                                        // verbose...
return (My_Variable == Another_Variable);       // More compact, and just as
                                                // lucid.

 

Goto statements are considered harmful.

A goto statement is a fallback many people use when they feel that the logic will get "too difficult to understand" if they write their code properly. It is, however, a problem which will cause code to be much more difficult to understand, and also more prone to error. The problem with gotos is that if you place a statement on the wrong side of a goto label, you could have a major problem on your hands. It is easiest to make the logic of your program flow in a linear fashion, so that you don't have to worry about finding a label when looking through source code, etc. There is no example for this guideline.

 

When using an I/O stream, always use "<< endl" instead of "<< '\n'".

endl, as well as displaying newline, has other advantages. The endl will flush the ostream buffer. The stream works by buffering up the output until it reaches a certain size or is explicitly flushed. Thereby, if you are outputting information with '\n', and your program terminates abnormally, the information will not be displayed on the screen. Please note that only the standard output stream, cout, is buffered. cerr is automatically flushed after each insertion. (Information extracted from C++ IOStreams Handbook by Steve Teale)

Example:

cout << "hello, world!\n"; // okay, but... 
cout << "hello, world!" << endl; // right! there's a new line there! 

 

If you are going to typecast, use the casting operators (if available).

The casting operators are a set of four operators (dynamic_cast, static_cast, const_cast, and reinterpret_cast) which allow you to change the type of a cast using a different set of rules. You should consult your compiler's online help to find out if the version you are using allows the use of casting operators, and what the differences between each of the types are as well as how to format the casts. There is no example for this guideline.

 

If the casting operators are unavailable, use the format "(type) (expression)".

Placing the parenthesis around what is being typecast is especially important because in the case of the order of operations, something may be typecast earlier or later than you want (or need!) it to. Although C++ allows you to use the type name without parenthesis, the use of parenthesis around the type name makes it obvious that this is a typecast, and not a function call.

Example:

My_Int = int (My_Unsigned);             // int () ... is that a function?
My_Int = (int) (My_Unsigned);           // Perfectly clear.

 


Classes

 

When defining a class, always explicitly declare the private: section.

The default protection level for a class is to have an implicit private: at the top of the class. This is okay, but if you explicitly declare your private section, you are more likely to visually spot problems such as methods being private which do not need to be, or member variables not being private which should be. There is no example for this guideline.

 

Always declare the protected: and public: sections, even if there is nothing in them.

This is another one of those maintenance helping things. If the section is already defined, you don't need to add the section identifier when you go to add more things to it anyway. Also, should you have a class large enough that you cannot see the entire class declaration on one screen, this will help prevent you from accidentally adding a section again (because you will know that the section already exists somewhere). There is no example for this guideline.

 

When deriving one class from another class, explicitly declare the inheritance type, even if it is private.

While you may remember that the default inheritance type when it isn't specified is private, there may be people out there who don't. But that's not the main reason. The main reason is that it shows that you really meant for the inheritance type to be private, not that you forgot to put one on there and now you are getting compiler errors because you can't reference now-private methods. There is no example for this guideline.

 

Always overload the "friend ostream& operator <<" function and output the contents in a nice, readable format.

99% of the time, this will only be done for debugging purposes. But you will have to admit that it would be much easier and nice to be able to add a cout << My_Class << endl; than it would be to try to create a function to output the parts that you need from the class, and then call it, and then remember to delete the method from the class later so that you don't screw up anything that already works. There is no example for this guideline.

 

When overloading "operator <<", do not include leading or trailing whitespace (including endl!) in your implementation.

While you can go ahead and format your contents however you choose, using as many or as few lines as you would like, chances are that the person who is calling you is going to do some formatting of their own as well immediately before and after calling your operator << function. If you go about adding whitespace at the beginning or the end, then the output may be something completely different than what is expected to be output. There is no example for this guideline.

 

When defining a class, always make the header file which includes the class declaration as the first #included file.

This will make it much easier to find the file which contains the class declaration if you want to augment some of the functionality, or possibly even go ahead and add new methods. While the .hpp file should have the same name as the .cpp file, having it included as the first entry will make it consistent and easy to find, even if, for some reason, the file names should be different. There is no example for this guideline.

 


Functions

 

It is acceptable to declare a function which is only called in one place.

If a certain operation being performed with some code has an excellent name that describes what it does, then feel free to break it out into its own function and have it called. Even if it is called only once, this has its advantage because it makes the code self-documenting. As well as self-documenting, should you ever need to have another place in the software perform the same operation, you can just call the existing function instead of cutting and pasting the code in somewhere else! There is no example for this guideline.

 

If a function is more than 100 lines long, consider the use of sub-functions.

Any overly-complex section of code can become difficult to follow, especially if there is a lot of smaller sub-sections which are being called sequentially. As mentioned above, it is acceptable to have a function which is only called once, so see if you can't find a perfect portion of your long function which could very logically be broken down into its own subfunction. There is no example for this guideline.

 

Always explicitly return from a function, even if it is a void function.

While there is not usually a problem with just falling off the end curly bracket of a function, if you have an explicit return statement, then it is much easier to change the return type of a function and find the existing return statement(s?) and change them to return a value instead of having to now go to the end of your function and add an all-new return statement. As well as that, it provides a cleaner approach. There is no example for this guideline.

 

Always put parenthesis around the value being returned.

Although in a lot of cases it doesn't make a difference, it makes the code more readable, and also will help to enforce what exactly is being returned from the function.

Example:

return 5;                               // Okay, but...
return (5);                             // ...this is much better!

 

Try to design your functions so that they only have one return statement.

It is not as easy to visually follow a function which has multiple exit points. While there may be times when it is advantageous to use multiple return statements as opposed to designing the function so it has only one return statement, it makes maintenance easier when changing the return type of a function (say, from void to int) to only have to change (without hunting, because you know it will be at the end) one return statement. One valid exception to this guideline is if you are comparing multiple states and are going to be returning a different error value based on which of the states are true, then you would be better off having multiple return statements as opposed to having a error value to return and checking to see if that value hasn't already been set before checking the next condition. There is no example for this guideline.

 


Files on Disk

 

A file with the extension of ".h" should generate no code or data.

Any file which has an extension of ".h" should follow the standard C rules for what is valid to be in an include file. There should only be declarations of functions, variables, constants, etc. in a ".h" file. There is no example for this guideline.

 

A file with the extension of ".hpp" may generate code or data.

If you want to declare inline functions with your class header, that is perfectly acceptable. However, you need to make sure that you have the extension of your file set to ".hpp" (if it is in an include file) if you are going to generate code. There is no example for this guideline.

 

Limit the placement of one class per source file.

There is no penalty for having more files, and it is advantageous (for reuse of classes) to have multiple classes split out into different files. This will allow you to include only the classes you need in your future projects, without bloating the size of your program with unnecessary objects being included. There is no example for this guideline.

 

When a source file gets to be longer than 1000 lines, consider breaking it down into multiple source files.

When a file gets to be unusually large, it becomes difficult to search through it attempting to find a function definition you are looking for, etc. Also, it ends up wasting a lot of paper when you are printing out a file and really what you want is some of the contents strewn throughout it. Again, there is no penalty for having more files, so this just makes it easier on everyone. There is no example for this guideline.

 

Include whatever keyword is supported by your SCM system to tell you the file name, revision, author, etc. in each of your source files.

This information is not only handy to have when you are looking at the source, but there are programs which can extract this information from the actual executable so that this information can be given to you by a customer. A major advantage to being able to do that is that you can now get the exact revision of each source code module that went into a build that a customer is using. There is no example for this guideline.

 

Do not put path locations (relative or absolute) in #include statements.

This makes it extremely difficult if you are attempting to use code in a place different than the original environment in which it was written (such as, for example, a notebook you have taken to a customer site to work on a problem).

Example:

#include "..\..\..\common\baseutil.h"   // I hope I have my tree set up right!
#include "e:\msvc\common\baseutil.h"    // Shoot!  E: is my CD-ROM!  Who set
                                        // this up!?
#include "baseutil.h"                   // I can now add e:\msvc\common to my
                                        // include directory list.

 

Never require other files to be #included before any other #include file.

If you create a header file to be included in a program or series of programs, it is obscene that you would make a requirement for your header file be that another header file has been already included. Instead of having this requirement which can waste time of the programmer trying to use you header file, you can just #include the files you need inside your own header file. So help out your fellow programmer. Save their time. Make their jobs easier. Wouldn't you want them to do the same thing for you?

Example:

// My include file.  This requires that <windows.h> already be included.
// ^-- Very bad.

// My include file.
#include <windows.h>
// ^-- Now I don't have to make sure I include <windows.h> before I include
// your file!

 

Always add a mechanism to prevent getting compiler errors if an include file is #included more than once.

If you accidentally (or unavoidably) #include the same include file more than one time, the compiler will generate a billion errors telling you that the token is already defined and so forth. The easiest mechanism to prevent this from happening is to pick some totally unique name (the name of the class, or even the file on disk, or a combination of both) for a preprocessor token. Then all you need to do is follow the example shown below and you will prevent from getting these errors.

Example:

#ifndef Totally_Unique_Token            // So if it isn't defined...
#define Totally_Unique_Token            // ...the define it...
// Include contents                     // ...and then declare your stuff...
#endif                                  // ...and now if the file is #included
                                        // again you won't get a compiler error.

 


Summary

Thank you for taking the time to reviewing our coding guidelines list. While there will always be valid exceptions to these guidelines, we hope that you will keep them in the recesses of your mind when you are coding in the future.

Contributors:

Victor A. Wagner, Jr.   Continuation Engineering
Scott C. Wagner   Continuation Engineering
Michael G. Hoernig   Continuation Engineering
Duc Tran   Continuation Engineering
William Coulter   Continuation Engineering
Kenneth T. Spoor   Continuation Engineering
Erik Weber   Custom Software Division

Questions? Comments? Insanely jealous that your name isn't in the contributors list? Email Scott Wagner, the editor of this list! You too can make a difference!


Glossary

angle bracket
The pair of characters which are sometimes used as inequality comparison operators, and are also used in conjunction with the cast operators to specify the type to be used with the cast operator. Visually, these characters appear as < and > in the Courier font.
bracket
Also known as braces. A character which has a counterpart, which is used to enclose text with a special meaning. The current bracket sets are: angle bracket, curly bracket, round bracket (more commonly known as parenthesis), and the square bracket.
close bracket
The last of a pair of brackets. The character which goes behind the surrounded text.
culled*
1. to pick out; to separate (one or more things) from others; to select and gather together from many; to collect; as, to cull flowers.
2. to sort over; to measure and to examine for quality; as, to cull lumber.
curly bracket
The pair of characters used in C and C++ to signify the beginning and of a code execution block. Visually, these characters appear as { and } in the Courier font.
open bracket
The first of a pair of brackets. The character which goes in front of the surrounded text.
parenthesis
The pair of characters most commonly used in C and C++. These characters are used for parameter lists as well as setting precedence in expressions. Visually, these characters appear as ( and ) in the Courier font.
square bracket
The pair of characters used in C and C++ for delimiting values out of an array. Visually, these characters appear as [ and ] in the Courier font.
tome*
1. originally, any volume of a work of several volumes.
2. a book, especially a large, heavy one.
vernacular*
commonly spoken by the people of a particular country or place: said of a language or dialect: often distinguished from literary.

* definitions used are from Webster's New Universal Unabridged Dictionary Deluxe Second Edition, Copyright c 1983, Simon & Schuster.


$Revision: 1.7 $
$Date: 97/06/03 15:51:39 $