You are here: Foswiki>WorldFoundry Web>OldCodingStandards (09 Apr 2002, KevinSeghetti;)Edit Attach

Old World Foundry Coding Standards

These guidelines were written in 1995, some of the reasons are no longer relevent.

File extentions:
  • .hp : C++ header file
  • .hpi : C++ inlines (included by the .hp file)
  • .cc : C++ code
  • .h : C header file
  • .c : C code

Never use multiple inheritance

Flawed in design and implementation

Never use exception handling. Flawed in implementation

Never put inline definitions in the class declaration.

All inlines should go in the .hpi files.

Never overload the following operators:

* (unary) & (unary) = = , ->* -> () ! &&

Never use a cast where a constructor conversion is occuring.

Use the new style of conversion.

Never pass NULL objects by reference.

For gcc this means that we swhould be able to compile with the -fnonnull-objects flag and preserve the correctness of the program.

Never use a const reference in a class.

This leads to ugly constructors and space inefficiency. Use inline fetch methods instead.

Never use the implicit copy constructors.

Strictly according to C++, if any public constructor is defined for a class T, then the constructor T::T(const T&) is implicitly defined. To insure that implicit copy constructors are not used inadverntently, each class which does not need such a constructor should declare a private version (and not implement it) so that using it causes a link error.

Avoid copy constructors in general.

If used, one must explicitly define these whenever needed, which is tedious as well as error prone (since one must always remember to updaetg the copy constructor when adding data members to a class). Each member should be explicitly copied. Note, however, that this allows for greater flexibility, such as copying of pointers containing non-shared state. Perhaps automatic verification for copy constructors could be implemented.

Avoid classes consisting of purely static members (modules).

These may be equivalently rewritten as normal members with a single static instance of the class, thus unifying class styles with more normal classes.

Avoid operator overloading unless it really makes sense, and makes the code more clear.

The only case this should be used for is types which are inherently numeric. Common examples are Scalar, Vector, and Matrix classes, which override all the integral operators as one would expect for linear algebra.

Avoid using pointers to functions or pointers to members.

There is probably a better way to do it.

Avoid explicit casts.

For example, when refining subclasses, use a virtual translation function instead (so that errors can be detected). Production versions may conditionally compile to casts where speed is important.

Avoid passing/returning classes.

Always comment the use of constructs mentioned above.

Use the keyword UNAVOIDABLE in a comment near such code.

Always use an explicit :: to mark the scoping of C++ external functions.

Always use meaningful names for identifiers, especially any identifier which has global scope.

We assue an oimplementation in whcih the first 31 characters are unique and case senstive for internal and external identifiers (note that ANSI only specifies 6 case insensitive characters for external identifiers, clearly insufficient).

Always use const for input only parameters.

ALso be sure to always label const functions as such. (The simplest way is to assume a const function until proven otherwise.

Usually pass objects by reference rather than pointers.

Unless one explicitly needs the concept of an invalid object (i.e. a NULL pointer), or one explicitly needs the concept of a pointer (e.g. for memory allocation).

Usually use constructors and destructors where it makes sense.

Thus initialization and cleanup are always in a known place. Do not be scared to use dynamic memory allocation, especially for initialization.

Conventions

We assume that all .cc files have a corresponding .hp .hpi (which may be empty). All externally visible class definitioins go in the .hp file, all inline definitions for such classes go in the .hpi file.The .hp file additionally contains any globally visible #defines, enums and/or typedefs associdated with the classe(es) defined. There will be no restriction about how many classes are defined in a .hp file (and of courfse corresponding .cc files).In the special case of a single class, however, the file name should strongly reflect the class name. In other cases the classes should be tightly releatd, such that inclusion into one interface makes sense. The .hp header includes the .hpi file and the end, usually wrapped with something whic looks like:
#if USE_INLINE_INCLUDES || defined(_ABSTRACT_CC)
#include "abstract.hpi"        /* include inline definitions */
#endif

This allows explicit compilation for non-inline versions, without relying on particular compiler implementations (which can be very usefull for debugging).

All headers are to be included only once, with the #ifndef/#define as the first thing in the file, followed by the banner, e.g.
#ifndef _ABSTRACT_HP
#define _ABSTRACT_HP
/* banner */
...
#endif    /*!_ABSTRACT_HP*/
We make an explicit mapping from filename to internal identifier as follows (given as a perl script):
tr/A-Za-z/a-zA-Z/;    # invert case for letters
s/[^A-Za-z0-9/_/g;    # anything weird (e.g. '.') becomes a _
s/^/_/;               # prepend an underscore
An alternative would be to simply go to uppercase, but this convention is attractive because it does not lose any information if filenames are restricted to letters, numbers, and '.'. Because of the DOS problem, file names should be 8 characters or less and only lower case (thus creating a simple translation from DOS to other).

Because we only conditionally include the inline definitions, we insist that instead of the keyword inline we use INLINE which may be conditionaly compiled to nothing for the case where we do not compile using inline functions. Also note that the .cc file expects the following as the first 2 lines of the file:
#define _ABSTRACT_CC
#include "abstract.hp"
This communicates the environment to the header file.

Naming conventions

Class names should be precedded by a 'Q'.

Class names should also follow the SmallTalk class naming convention of having the first letter of words being capitalized, e.g. QClonableObject. Enumeration type names should similarly treaded, except for beginning with an 'E', e.g. EZoomState.

!#defined constants, const values, or enum constants should be all uppercase to indicate their status. Enumeration constants have the additional constraint of beginning wit EXXX_, where XXX is an optional enumeration type indicator, e.g. enum EZoomState (EZS_NONE, EZS_ZOOM_IN, etc.)

typedefs of primitive types (which should be the onloy kind used, typically), should be lowercase, with a trailing "_t". This convention is rooted in ancient UNIX/C tradiion. This is also not a strict convention, for example the primitive types uint16, etc, do not follow this because their meaning is clear from the name. For less obvious types, however, this convention quickly alerts the reader to the meaning of the symbol.

Class data members must always begin with an '_', which immediatly distinguishes them from local variables or function parameters.

Function names shoudl begin with a lower case, but otherwise capitalize the beginnings of words.

Local variables and function arguments(except boolean flags) should be all lowercase.

Functions which take boolean arguments should define, as part of the interface, symbolic names which indicate what they do, e.g.:
#define bGenError bTrue
#define bNoGenError bFalse
...
getCelRefFromDB(const char* name, Bool fGenError);
This makes the use of such functions much more readable. Notice the implicit naming convention for such boolean constants. I happen to like this convention even though it violates the all upper case convention for constants.
Access functions should typically be the same name as the data they represent for the fetch (with no leading '_'), similarly for the set function, except with a leading "set", e.g.:
public:
    sometype    nameOfData(void) const;
    void        setNameOfData(sometype);
private:
    sometype    _nameOfData;

Base types and constants

In addition to basic types and constants defined in ANSI, such as size_t and NULL, several common types are defined to help facilitate portability. These include the following integral sized types and abbreviated notations:
int8    uint8    int16    unint16    int32    uint32
uchar   ushort   uint     ulong

In addition to the integral types a boolean type is defined: Bool. This is almost guaranteed to be type int, since one prefers the natural machine size. (In particular it will not in general be of type char.) The following are predefined boolean constants:
#define TRUE    (1!=0)
#define FALSE   (1==0)
#define bTrue   TRUE
#define bFalse  FALSE

OldCodingStandards2 (phpwiki seems to have a problem with long pages)
Topic revision: r1 - 09 Apr 2002, KevinSeghetti;
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback