Best Practice - Coding Style

Rationale

Documentation

Readable Code

Identifiers

Identifier Syntax (Limited Character Set)

Identifier Syntax (Full Character Set)

Identifiers for Shells and Makefiles

Indenting

Spaces

Modularity

Function Size

Duplicate Code

Single Entry Source Files

Resource Leaks

Function Returns

Debugging Statements

Source File Structure

Function Source File

Include Source File

Object Oriented Source File

Makefile

Script File


 

Coding Style Best Practices

The number one goal of the Coding Style Best Practice is to encourage a coding style that results in code that is easily understood by a programmer using or modifying the code at a future date. The keys to understandable code are correct documentation, descriptive variable and function names and creation of small modular functions.

Documentation

See the Source File Documentation Best Practices.

Readable Code

Identifiers

The most important feature of readable source code is well chosen identifiers. Identifiers are names for variables, constants, functions, structures, classes, types and macros.

The general rule for choosing identifiers is to use a combination of whole words or commonly accepted abbreviations for words. Whole words are better then abbreviations. Commonly accepted abbreviations include abbreviations used by convention in the software industry. Example: 'fd' is a commonly used abbreviation for 'file descriptor'. There shall not be more than one abbreviation for the same word within a file. Abbreviations must be consistent.

Developers are strongly encouraged to use multiple word identifiers. Multiple word identifiers greatly enhance code readability. Since a function performs an action a function identifier should contain a verb. Variables or parameters generally hold a 'thing' so a noun and adjective that describe the 'thing' are use as an identifier.

The only time a single letter identifier is allowed is as the identifier for an index counter.

Limited Character Identifier Syntax

This method of creating identifiers applies to languages that restrict identifier characters to upper and lower case alphabetic, numbers and underscore.

When using multiple words and abbreviations in an identifier the first letter of the second and succeeding words or abbriviations must be capitalized. The second and succeeding letters in each word or abbreviation must be lower case. The requirements for capitalization of the first character of an identifier should be set by each project. A good rule is that the first character of a function identifier is capitalized. The first character of variable and parameter identifiers is lower case.

Macro identifiers in a 'C' or 'C++' language file must all be upper case.

Words and abbreviations may be optionally separated by the '_' character.

Unlimited Character Identifier Syntax

This method of creating identifiers applies to languages that place almost no restrictions on the characters that can be used to compose an identifier. These identifiers consist whole words with the '-' character separating the words.

In the LISP language the following conventions apply:

Shell and Makefile Identifiers

All file scope parameters, environment variable identifiers and makefile macros are in uppercase with optional underscore characters separating the identifier's words and abbreviations. Shell/Script function identifiers have the same requirements as described in the Limited Character Identifier Syntax section.

Indenting

For each control structure/statement occurring in the code the contents of the structure must be uniformly indented at least two spaces from the level of indentation of the containing control structure/statement.

Example:

if ( expression ) {
statements1;
while ( stuffToDo ) {
statements2;
}
statements3;
}

In this example the contents of the 'if-then' clause are indented 2 spaces. The contents of the 'while' loop are indented 2 more spaces.

If you use the Emacs text editor you can take advantage of the language senstive editing capabilities for intelligent indenting.

Spaces

Spaces are used not only to indent levels of control statements but to make each line of code more readable. Spaces should be used as follows:

Example:

printf( stdout, "hello %d\n", countHellos( currentHelloCount + additionalHellos );

Line Length

 

Modularity

Modularity involves writing functions that perform a single task or a few small closely related tasks. This enhances code readability and facilitates code reuse.

Function Size

Source code for functions should not exceed 100 lines. There are rare instances where longer functions are needed.

If a function exceeds 100 lines, generally there are at least 2 easily identifiable and separable tasks being performed by the function. One or more of the tasks should be placed in new separate functions. If there are 2 or more outer loops it is likely that all but one of the loops should be placed in new separate functions.

Using small functions makes the code easier to read by breaking it up. Function identifiers for small functions are more specific in identifying each function's task making the code easier to understand.

Duplicate Code

When a code developer is tempted to copy a few lines of source code from one function to use in another function, always create a new function for the code that would have been copied. Replace the original code with a call to the new function.

With copied code it is invariable that at some point in time the copied code will be changed in one location. This will require the same change to be made in every location the code was copied to. Almost always a bug is introduced because the developed either forgot to change a copy or didn't know about a copy of the code. It is more efficient and less bug prone to place the code into a single function so that future changes can be made in a single location.

The duplication rule applies to files also. If there is a file that would be useful in more than one program, place the file in a common access location. For 'C' include files a common include directory should be used. For a 'C' source file containing a function useful to more than one application the file/function should be placed in a library that can be linked by each application.

Single Entry Source Files

Source code files should contain a single entry function. An entry function is a function called by functions outside the scope of the file.

There may be multiple file scope functions with in the file. A file scope function is a function that is only called by other functions within the same file.

In the 'C' language a function has file scope when it is defined 'static'.

For 'C' source files the name of a file must be the same as its entry function name.

The member functions for a 'C++' class may all be placed in the same file with the name of the file being the name of the class.

Resource Leaks

A resource leak occurs when a program does not release a dynamic resource when the resource is no longer needed. If the program continually acquires resources without releasing them the program will typically fail. The cause of the failure is frequently difficult to determine.

Memory Allocation/Deallocation

Any memory that is allocated by a program must be freed when it is no longer needed. Obviously this only apples to languages like 'C'. Languages like Lisp and Java provide automatic allocation and deallocation.

File Descriptors

Any file descriptor that is opened/bound must be closed when it is no longer needed.

Function Returns

Only return from the end of a function's code. Multiple return locations within a function create code that is very prone to coding errors and makes maintenance difficult.

Debugging Statements

(TBS)

Source File Structure

Readability of source code is enhanced by a consistent organization of the of the code for each source file.

Function Source File

(TBS)

Heading

Includes

[File Scope Objects/Structures/Types]

[File Scope Variables]

[File Scope Function Declarations]

[File Scope Usage Function Definitions]

Entry Function Definition

[File Scope Function Definitions]

Here is a 'Main' source file template in the C language. Here is a generic source file template in the C language.

Include Source File

(TBS)

Heading

Includes

[Macros]

[Objects/Structures/Types]

[Function Declarations]

Here is a source 'include' file template in the C language.

Object Oriented Source File

(TBS)

Here is a source file template in the Java language.

Makefiles

(TBS)

Heading

Includes

Macros

Rules

Dependencies

Here is a template for a C application makefile and a template for a Java application makefile.

Here is a template for C library makefile.

Here is a template for a directory makefile.

Here is a template for a test makefile.

Script Files

(TBS)

<sh template>