General Coding Guideline



The main purpose of this guideline is to make sure the programs written by different people follow a consistent style, so that it is easy for everybody to understand and modify the code.

Naming:

1. Use meaningful names for classes and methods. If a name consists of multiple words, separate words by using underscores or capitalize the first letter of each word. It may not be a good idea to use names such as "a, b" or "arg1, arg2".

2. For global names (top level classes, functions, variables), do not use very common words to avoid name collision.

File names:

3. All header files use suffix .h, all C files use suffix .c, all C++ files use suffix .cc.

4. Typically, a module has a header file .h and a implementation part .cc or .c file. The stem of the two files must be the same.

Indentation style:

4. The first line of the .cc files must be:
// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:t -*-

5. The first line of the .c file must be:
// -*- mode:C; tab-width:4; c-basic-offset:4; indent-tabs-mode:t -*-

6. For .h files, depends on whether it is written in C++ or C, you may choose between 4 or 5 respectively.

Header file:

7. Header files should follow the following format:

# ifndef __XYZ_H__
# define __XYZ_H__

// put body here.
...

# endif

8. If a module xyz is written in C, with its interface defined in xyz.h, hen we should enclose the whole body using the following construct:

# ifdef __cplusplus
 extern "C"  {
# endif

// put body here
...

# ifdef __cplusplus
}
# endif

Copyright notice:

9. The copyright notice should follow immediately after the indentation line.

10. A brief description of the file and the authors should follow the copyright notice.

Interface design guidelines:

11. Try to make sure that the interface is defined by necessity.

11.1 If a declaration can be put in the .c or .cc files, then do so.

11.2 If a method should not be called by external programs, declare it as private.

11.3 If we only need to keep a pointer of an object, then we do not really need to include the class interface file. Instead, we can simply write a line "class ReferedClass".

11.4 If there is no dependence or hierarchy among the functions inside a .cc file, sort them by their names to make reading the code easier.

12. Method inlining. Only do so when the method is very short.

Miscellaneous:

13. Constructors. The simple initialization of member variables in the constructor should follow the member variable initialization style, aka:

Constructor(...) :
var1(...),
var2(...)
{
...
}

14. If you need to refer to a constant multiple times, try to do "# define" or "enum" (only apply to integers).
My rules of thumb are:
(a) if the constant is not part of the interface, put them in .c .cc or in the class definition's "private" section (for enum only), and vice versa.
(b) if the constants are tightly coupled with the class, put them as enum inside the class.

15. If most of the fields you are going to manipulate directly, try to use "struct" instead of "class".

16. It is a bad habbit to put "printf" or "cout <<" in the program. Instead, try to use the "tmpi_debug" module (this allows you to do dynamically change from console output to log file output without changing the programs).

Error Handling:

It is a complicated situation when it comes to error handling.
There are several mechanisms when may use:
(1) return an error status from a function.
(2) throw an exception.
(3) assertion failure.
(4) print out error messages.

The following guidelines range from relatively conventional and typical usage to empirical rules in my common practices.

(a) assertion should be (and only be) used to test invariance which should always hold (such as the object's internal status). If the assertion fails, the program will be core-dumped. It is meant to be used in situations when something should have never happened occurred. For example, if you implement a double-link list, then for each item, you can assert(item->next->previous == item). If an assertion fails, it typically should reflect some logical bug in the program. Bad input parameters typically should not be considered (there are exceptions).

(b) Failure in constructor should throw an exception. Since there is no return value of constructors, I think it is better to throw an exception instead of keep the program running. (Some of my old code does not follow this rule, instead, I set a status variable inside the object, and provide a function good() to check whether the initialization succeeds or not).

(c) Error message or logging is an effective way to monitor a server program in the long run (the server may have passed various short tests, and is put into production use, and logging allow us to detect problems that only show up in the long run.) Currently the "tmpi_debug" module should suffice the purpose, I am planning to add more features to that module. On the other hand, DO NOT directly print out error messages, because your program may not run in console mode (may not even have a terminal associated with it). Also, the main program may have its own control of terminal (using ncurse library). And console output would mingle with the terminal output.

(d) I personally do not see a clear cut between returning error status and throwing exceptions. This is probably due to the fact that the error status approach is compatible with a large amount of legend code pre-dated C++. In general, exception should be a better way to report errors, particularly UNEXPECTED ERRORS. This would simplify the flow of the caller functions and make them easy to understand. On the other hand, for errors that can be reasonably expected (for example, file not found, end of the file), it is probably better to use error status instead of exceptions.

(e) The ideal situation of error reporting is to concatenate error messages while the stack unwinds (through either return or throw). The error may eventually either be handled at a level that has sufficient knowledge to recover from the error; or may just be dumped to the log or screen and the program quits.

Last modified: Mon Jul 21 21:58:37 PDT 2003