Difference between revisions of "Standards for Programming Practice"
(Created page with " E.1 C++ Language Conventions Access to Data Members Don’t make any class data member public without good reason. One example of appropriate public data member is the case w...") |
|||
(9 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | + | ==C++ Language Conventions Access to Data Members== | |
− | + | ||
Don’t make any class data member public without good reason. | Don’t make any class data member public without good reason. | ||
One example of appropriate public data member is the case where the class is essentially a data structure, with no behaviour. In other words, if you would have used a struct instead of a class, then it’s appropriate to make the class’s data members public. | One example of appropriate public data member is the case where the class is essentially a data structure, with no behaviour. In other words, if you would have used a struct instead of a class, then it’s appropriate to make the class’s data members public. | ||
− | + | ||
+ | ==C Language Conventions== | ||
Use the Standard C syntax for function definitions: | Use the Standard C syntax for function definitions: | ||
− | + | ||
− | + | void example_function (int an_integer, long a_long, short a_short) | |
− | If the arguments don’t fit on one line, split the line | + | ... |
− | void example_function (int an_integer, long a_long, short a_short, | + | |
− | + | If the arguments don’t fit on one line, split the line like this, | |
− | ... | + | |
+ | void example_function (int an_integer, long a_long, short a_short, | ||
+ | float a_float, double a_double) | ||
+ | ... | ||
+ | |||
Declarations of external functions and functions to appear later in the source file should all go in one place near the beginning of the file (somewhere before the first function definition in the file), or else it should go in a header file. | Declarations of external functions and functions to appear later in the source file should all go in one place near the beginning of the file (somewhere before the first function definition in the file), or else it should go in a header file. | ||
− | Do not put extern declarations inside functions. | + | |
− | Use of Guards for Header Files | + | Do not put extern declarations inside functions. |
+ | |||
+ | ==General Issues== | ||
+ | |||
+ | ===Use of Guards for Header Files=== | ||
+ | |||
Include files should protect against multiple inclusion through the use of macros that guard the file. Specifically, every include file should begin with the following: | Include files should protect against multiple inclusion through the use of macros that guard the file. Specifically, every include file should begin with the following: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | Conditional Compilation | + | #ifndef FILENAME_H |
+ | #define FILENAME_H | ||
+ | ... header file contents go here | ||
+ | #endif /* FILENAME_H */ | ||
+ | |||
+ | In the above, you should replace <code>FILENAME</code> with the root of the name of the include file being guarded e.g. if the include file is cognition.h you would write the following: | ||
+ | |||
+ | #ifndef COGNITION_H | ||
+ | #define COGNITION_H | ||
+ | ... header file contents go here | ||
+ | #endif /* COGNITION_H */ | ||
+ | |||
+ | ===Conditional Compilation=== | ||
Avoid the use of conditional compilation. If your code deals with different configuration options, use a conventional if-else construct. If the code associated with either clause is long, put it in a separate function. For example, please write: | Avoid the use of conditional compilation. If your code deals with different configuration options, use a conventional if-else construct. If the code associated with either clause is long, put it in a separate function. For example, please write: | ||
− | + | ||
− | + | if (HAS_FOO) { | |
− | } | + | ... |
− | else { | + | } |
− | ... } | + | else { |
+ | ... | ||
+ | } | ||
+ | |||
instead of: | instead of: | ||
− | + | ||
− | + | #ifdef HAS_FOO | |
− | #else ... | + | ... |
− | #endif | + | #else |
− | Writing Robust Programs | + | ... |
− | Avoid arbitrary limits on the size or length of any data structure, including arrays, by allocating all data structures dynamically. Use malloc or new to create data-structures of the appropriate size. Remember to avoid memory leakage by always using free and delete to deallocate dynamically- created data-structures. | + | #endif |
− | Check every call to malloc or new to see if it returned NULL. | + | |
− | You must expect free to alter the contents of the block that was freed. Never access a data structure | + | ===Writing Robust Programs=== |
− | after it has been freed. | + | |
− | If malloc fails in a non-interactive program, make that a fatal error. In an interactive program, it is better to abort the current command and return to the command reader loop. | + | Avoid arbitrary limits on the size or length of any data structure, including arrays, by allocating all data structures dynamically. Use <code>malloc</code> or <code>new</code> to create data-structures of the appropriate size. Remember to avoid ''memory leakage'' by always using <code>free</code> and <code>delete</code> to deallocate dynamically-created data-structures. |
− | When static storage is to be written during program execution, use explicit C or C++ code to | + | |
− | + | Check every call to <code>malloc</code> or <code>new</code> to see if it returned <code>NULL</code>. | |
− | + | ||
− | + | You must expect <code>free</code> to alter the contents of the block that was freed. Never access a data structure after it has been freed. | |
− | + | ||
− | Constants | + | If <code>malloc</code> fails in a non-interactive program, make that a fatal error. In an interactive program, it is better to abort the current command and return to the command reader loop. |
+ | |||
+ | When static storage is to be written during program execution, use explicit C or C++ code to initialize it. Reserve C initialize declarations for data that will not be changed. Consider the following two examples. | ||
+ | |||
+ | static int two = 2; // two will never alter its value | ||
+ | ... | ||
+ | static int flag; | ||
+ | flag = TRUE; // might also be FALSE | ||
+ | |||
+ | ===Constants=== | ||
+ | |||
Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values. | Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values. | ||
− | Variable Assignments | + | |
+ | ===Variable Assignments=== | ||
+ | |||
Avoid assigning several variables to the same value in a single statement. It is hard to read. | Avoid assigning several variables to the same value in a single statement. It is hard to read. | ||
+ | |||
Do not use the assignment operator in a place where it can be easily confused with the equality operator. | Do not use the assignment operator in a place where it can be easily confused with the equality operator. | ||
− | if (c++ = d++) { // AVOID! | + | if (c++ = d++) { // AVOID! |
− | + | ... | |
− | } | + | } |
+ | |||
should be written as | should be written as | ||
− | |||
− | |||
− | |||
+ | if ((c++ = d++) != 0) { | ||
+ | ... | ||
+ | } | ||
Do not use embedded assignments in an attempt to improve run-time performance. This is the job of the compiler. | Do not use embedded assignments in an attempt to improve run-time performance. This is the job of the compiler. | ||
− | + | ||
+ | d = (a = b + c) + r; // AVOID! | ||
+ | |||
should be written as | should be written as | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | a = b + c; | |
+ | d = a + r; | ||
+ | |||
+ | ===Parentheses=== | ||
+ | |||
+ | Use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others — you shouldn’t assume that other programmers know precedence as well as you do. | ||
+ | |||
+ | if (a == b && c == d) // AVOID! | ||
+ | if ((a == b) && (c == d)) // USE | ||
+ | |||
+ | ===Standards for Graphical Interfaces=== | ||
+ | When you write a program that provides a graphical user interface (GUI), you should use a cross-platform library. The FLTK GUI library satisfies this requirement. | ||
+ | |||
+ | ===Error Messages=== | ||
+ | Error messages should look like this: | ||
− | + | function_name: error message | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + |
Latest revision as of 03:46, 20 January 2020
Contents
C++ Language Conventions Access to Data Members
Don’t make any class data member public without good reason. One example of appropriate public data member is the case where the class is essentially a data structure, with no behaviour. In other words, if you would have used a struct instead of a class, then it’s appropriate to make the class’s data members public.
C Language Conventions
Use the Standard C syntax for function definitions:
void example_function (int an_integer, long a_long, short a_short) ...
If the arguments don’t fit on one line, split the line like this,
void example_function (int an_integer, long a_long, short a_short, float a_float, double a_double) ...
Declarations of external functions and functions to appear later in the source file should all go in one place near the beginning of the file (somewhere before the first function definition in the file), or else it should go in a header file.
Do not put extern declarations inside functions.
General Issues
Use of Guards for Header Files
Include files should protect against multiple inclusion through the use of macros that guard the file. Specifically, every include file should begin with the following:
#ifndef FILENAME_H #define FILENAME_H ... header file contents go here #endif /* FILENAME_H */
In the above, you should replace FILENAME
with the root of the name of the include file being guarded e.g. if the include file is cognition.h you would write the following:
#ifndef COGNITION_H #define COGNITION_H ... header file contents go here #endif /* COGNITION_H */
Conditional Compilation
Avoid the use of conditional compilation. If your code deals with different configuration options, use a conventional if-else construct. If the code associated with either clause is long, put it in a separate function. For example, please write:
if (HAS_FOO) { ... } else { ... }
instead of:
#ifdef HAS_FOO ... #else ... #endif
Writing Robust Programs
Avoid arbitrary limits on the size or length of any data structure, including arrays, by allocating all data structures dynamically. Use malloc
or new
to create data-structures of the appropriate size. Remember to avoid memory leakage by always using free
and delete
to deallocate dynamically-created data-structures.
Check every call to malloc
or new
to see if it returned NULL
.
You must expect free
to alter the contents of the block that was freed. Never access a data structure after it has been freed.
If malloc
fails in a non-interactive program, make that a fatal error. In an interactive program, it is better to abort the current command and return to the command reader loop.
When static storage is to be written during program execution, use explicit C or C++ code to initialize it. Reserve C initialize declarations for data that will not be changed. Consider the following two examples.
static int two = 2; // two will never alter its value ... static int flag; flag = TRUE; // might also be FALSE
Constants
Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values.
Variable Assignments
Avoid assigning several variables to the same value in a single statement. It is hard to read.
Do not use the assignment operator in a place where it can be easily confused with the equality operator.
if (c++ = d++) { // AVOID! ... }
should be written as
if ((c++ = d++) != 0) { ... }
Do not use embedded assignments in an attempt to improve run-time performance. This is the job of the compiler.
d = (a = b + c) + r; // AVOID!
should be written as
a = b + c; d = a + r;
Parentheses
Use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others — you shouldn’t assume that other programmers know precedence as well as you do.
if (a == b && c == d) // AVOID! if ((a == b) && (c == d)) // USE
Standards for Graphical Interfaces
When you write a program that provides a graphical user interface (GUI), you should use a cross-platform library. The FLTK GUI library satisfies this requirement.
Error Messages
Error messages should look like this:
function_name: error message