Sunteți pe pagina 1din 16

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 lways 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:

• It becomes difficult to differentiate between two identifiers which have the same first 20 characters.
• The amount of useful information in one screen or paper width is more limited.
• It takes too long to type them.

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 already be included.


// ^-- Very bad.

// My include file.
#include
// ^-- Now I don't have to make sure I include 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 $

S-ar putea să vă placă și