Table of Contents
- 1.0 Introduction
- 2.0 Naming Conventions
- 2.1 Variable Names
- 2.2 Character names
- 2.3 Pointer Names
- 2.4 C-style Arrays
- 2.5 STL Class Names
- 2.6 Function Names
- 2.7 Class Names
- 2.8 Struct Names
- 2.9 Enumation Names
- 2.10 Include Guard Names
- 3.0 Indentation
- 3.1 emacs support
- 4.0 Namespace
- 5.0 Diagnostic Function
- 6.0 Group Policy
- 6.1 CVS
- 6.2 Compiling Code
- 6.3 Incomplete Code
- 7.0 Compiler Compatibility
- 7.1 g++
- 7.2 Visual C++ .NET
1.0 Introduction
This page contains the most up-do-date version of the EGAD Library coding conventions. I will e-mail all updates to this document to those interested. The document is organized by category and hopefully isn't too confusing to navigate. Send all comments and insults to Arnab <achowdry@leafnode.net>
2.0 Naming Conventions
2.1 Variable Names
Variable names should begin with a lower-case letter, and all distinct words in a variable name should be distinguished by capitalizing the first letter. Do not use underscores in variable names. Name all variables so that their type is apparent from reading their name. This is accomplished by beginning all variable names with a character indicating their type.
// cInteger types (int, short, long):
int iMaxCount; short iShortCount;
// Float types (float, double):
float fSomeFloat; double fSomeDouble;
// C-style strings (char arrays):
char strMyName[200];
// Booleans (bool):
bool bFlag;
2.2 Character Names
Characters are a special case, because the lowercase ‘c’ prefix is reserved for classes in standard Hungarian notation. Though the EGAD convention does not reserve c for such a purpose, it could cause confusion if we were to change its standard meaning. The prefix ‘a’ is used for char types
// Character types:
char aChar;
2.3 Pointer Names
Prefix all pointers with lowercase 'p'. Add as many p's as there are levels of indirection. Otherwise, name them as you would any other variable.
// Pointer types:
Protein *pSomeProtein;
Protein **ppSomeProtein;
2.4 C-style Arrays
Treat C-style arrays as pointers of the appropriate type.
// C-style arrays:
int pMyArray[30];
2.5 STL Class Names
The STL contains many common classes that are often used in development. It is difficult to come up with prefixes for all available classes, but the following are useful to keep in mind. If you make up your own for other STL classes, do not use single-letter abbreviations. Since there are so few of them, we have to reserve them for base types.
// STL Class Names
string objects: strName;
stringstream objects: ssName;
vector objects: vecContainer;
2.6 Function Names
Function names should begin with an uppercase letter and, like variables, should have distinct words distinguished by capitalization of the first letter.
// Function Names
void MyFunction();
2.7 Class Names
Classes should start with a uppercase letter and, like variables, should have distinct words distinguished by capitalization of the first letter.
// Class Names
class MyClass;
2.8 Struct Names
Structs should be named as classes are, but should be preceeded by a lowercase 's' to distinguish them from classes. Note that, while a struct CAN have private members in C++, you should not create structs with private members. If you require private members, use classes.
// Struct Names
struct sMyStruct;
2.9 Enumeration Names
All enumerations and members of enumerations should be named in all-caps. Use underscores to separate words for clarity.
// Enumerations
enum MY_PETS { DOG, CAT, WOMBAT };
2.10 Include Guard Names
Include guards are found at the beginning and ends of header files to prevent their contents from being included multiple times. It is useful to have a naming convention for them to prevent naming overlap. When naming include guards, use the filename of the header file, in all caps, with underscores '_' replacing period(s).
// For EGAD_HeaderFile.h
#ifndef EGAD_HEADERFILE_H
#define EGAD_HEADERFILE_H
// ...
#endif
3.0 Indentation
Indentation of matching brackets should match. Any items within a pair of brackets should be indented at least one step more than the brackets themselves. While this may produce more blank-space in the code, it really increases readability:
// Do this:
for (int i = 0; i < 5; i++)
{
cout << i;
ProcessIndex(i);
}
// Not this:
for (int i = 0; i < 5; i++){
cout << i;
ProcessIndex(i);
}
Alternatively, if your coding style dictates that you must use the latter form, make sure to comment the ends of your brackets to note what they are closing:
for (int i = 0; i < 5; i++){
cout << i;
ProcessIndex(i);
}//end for
When continuing a command on the next line, indent at least one space, but do not further indent future continuations of the same command:
int iNumber = ThisFunctionHasManyParameters(iParam1,
fSomeOtherParam2, strAStringParam, fParam4,
iAFinalParam);
3.1 emacs support
If you use emacs as your IDE, try adding the following to your .emacs file to get indentation working correctly:
;; Use literal spaces rather than tabs for indenting (setq-default indent-tabs-mode nil) ;; Indent like Bjarne, the crazy Dane. (setq c-default-style '((other . "stroustrup")))
4.0 Namespace
All parts of the EGAD Library should be in namespace Egad. For header files (.h), place all class/struct/function definitions within brackets as shown below. For implementation files (.cpp), place a "using namespace Egad;" declaration near the top of each file. For non-member functions, you must preceed their definitions in any implementation file with Egad:: to scope them into the Egad namespace. Otherwise, your code will not compile.
// Header files
#include "EGAD_Error.h"
namespace Egad{
class MyClass{
int iSomeInt;
public:
void MemberFunction();
// ...
};
void NonMemberFunction();
}
// Implementaiton Files
using namespace Egad;
// Member functions as usual
void MyClass::MemberFunction()
{
// ...
}
// Non-member function
void Egad::NonMemberFunction()
{
// ...
}
5.0 Diagnostic Function
All classes should contain a public diagnostic dump function that will print all relevant information about the class to an output stream. The prototype for the function should look like this:
// Diagnostic Dump
void DiagDump(std::ostream &out = cout) const;
6.0 Group Policies
Because there are many people working on the same set of code at once, it is necessary to have a few group polices to prevent redundant work.
6.1 CVS
When using CVS, update often. Updating does not change the server-copy of the code, and will catch conflicting code quickly before you spend too much time on it. If code you wrote conflicts with the CVS code, find out who wrote the current version and work out the conflict with them in person. Remember, your changes must be committed to the server before others are able to view them. Use the "add" command to add new files (you still need to commit after adding for the files to actually upload themselves).
6.2 Compiling Code
Strive to have a compiling version of the code to upload to CVS by the end of the day. If your code won't compile, it is still okay to commit your changes, if you feel comfortable that it will compile sometime soon. Also, please take note of the differences between compilers and read the cautionary notices later in this document.
6.3 Incomplete Code
If there are parts of your code that you haven't written yet, make sure you mark them so that both you and others know what still needs to be implemented. The accepted way to mark such code is to use "// TODO" followed by any comments you have about the code. The TODO is necessary to facilitate searching for incomplete code.
class Protein{
protected:
std::vector <BackPos*> vecBackbone;
// ...
public:
// TODO
// I haven't gotten around to implementing the protein yet
};
7.0 Compiler Compatibility
The goal of the EGAD Library is to be as standards-compliant as it can be, while still maintaining the widest level of portability in the code. This is a lofty goal, and the following notes are important to achieving it:
7.1 g++
The g++ compiler is used by most coders using Linux. g++ is a very forgiving compiler when it comes to breaking standards. In particular, g++ overlooks many mistakes when using the STL. Remember to always use namespace std when using STL.
// The wrong way, but will compile under g++
#include <vector>
void MyFunction()
{
vector<int> vecMyVector;
// There is nothing to specify that vector is a member
// of namespace std. Under most standards-compliant
// compilers, this will not compile.
}
// The right way, which will still compile under g++
#include <vector>
void MyFunction()
{
std::vector<int> vecMyVector;
}
7.2 Visual C++ .NET
Visual C++ .NET is the windows compiler used by the EGAD Library. .NET is ANSI standards compliant to a fault. One case where this causes problems is when declaring static const member variables inside of a class. Visual C++ will not allow initialization of non-integer types within the class declaration. Strangely enough, the standard agrees with this, and only integer types are allowed to be initialized inside of a class. For a more general solution, initialize all of your static const member variables outside of the class declaration, like this:
// Wrong way:
class MyClass{
static const int iSomeNumber = 4;
static const double fSomeDouble = 4.52; // Error
};
// Right way:
class MyClass{
static const int iSomeNumber;
static const double fSomeDouble;
};
// elsewhere, in implementation file
const int MyClass::iSomeNumber = 4;
const double MyClass::fSomeDouble = 4.52;