- Each larger class has its own header file *.h and one ore more *.cpp files. In exceptional occasions, if there are few small auxiliary classes that are related together, they can be placed in one header file. However, auxiliary classes should be encapsulated in major class.
- It is highly recommended to include header files into other header files only if you really need them. Forward declarations should be used for other classes. There is only one exception to this rule: server classes. They can include all most used objects. Therefore, do not include server classes into other header fieles!
- Definitions of small and often used methods lies directly in header file. It is necessary to find rational balance between this rule and previous rule. It is often better to abandon inline funcion and not to include whole other module into the header file. Bodies of inline functions don't lie in class declaration but under the class (even if they contains only one line of code).
- Each header file includes system.h file appropriate to current module. For example:
- Each file contains definition for vim editor at the end. There is a new empty line after this definition.
- You must use 'NEW' macro instead of 'new' operator to create objects. This macro cooperates with internal memory system used to detect memory leaks. Standart 'delete' operator is used to free memory.
- Global functions are not allowed except functions for script interface. If you need them, you should think about better design of data structures. Good method how to create "global" functions encapsulated in some nice class is to use static functions. For example:
class Utils
{
static B ConvertA2B(A a);
static A ConvertB2A(B b);
};
- Global variables... are you kidding? In some occasions, if you have really good reason, you can use static variables. This is used for example in server classes (singletons).
- Function that contains more than 100 lines is suspected. Functions that contains more than 200 lines is not allowed.
- The 'this->' clausule must be written before calling member functions or using member variables. This is helpful for recognize local variables. For example:
void function Class::DoSomething(int param)
{
this->result = this->DoSomethingElse(param);
}
- It is recommended to follow these name conventions for variables and parameters used for file paths:
- path - path composed only from folders is expected (without file name and slash at the end)
- file_name - file name together with extension
- file_path - file name together with extension and absolute or relative path (path/file_name)
- Tabs are used for indent. Area between commands and comments is filled by spaces. For example:
class Class
{
--->int nimber;________
--->char *string;______
}
Where ---> is tabulator, _ is space.
- Curly brackets are used if next block of code contains more than one line or in case of long conditions. Left curly bracket is always placed on new line. For example:
if (condition)
OneLine();
if (condition)
{
FirstLine();
SecondLine();
}
if (condition1)
{
if (condition2)
SecondLine();
}
if (condition1 || condition2 || condition3 ||
condition4 || condition5 || condition6)
{
OneLine();
}
do
{
OneLine();
} while (condition)
void Class::Function()
{
FuncionBody();
}
- Names of variables are lower case, words are separeted by underscores. Names of classes, structures and enumerated types contains capital letter at the beginning of each word, underscores are not used. The same rule applies for names of methods and macros. Moreover, methods and macros begin with verb that reflect its primary functionality. Functions returning boolean value, that represents state of the object, begin with 'Is', 'Has' or 'Can' verb. Functions that set/get parameters begin with 'Set' or 'Get' verb. Enumerated values are upper case, words are separeted by underscores. They begin with short prefix that shows the enumerated type thay belongs to.
- Declarations of classes contain three blocks: -- embeded - for embeded classes, structures and enumerated types -- methods - for member functions -- variables - for variables
Each block contains 'public', 'protected' or 'private' part (in this order).
For example:
class DataFile
{
public:
enum LoadState
{
STATE_UNLOADED,
STATE_BLOCK_LOADED,
STATE_LOADED
};
public:
bool Open();
void Close();
bool LoadData();
void SetFileName(const string &file_name);
LoadState GetState();
bool IsOpened();
protected:
DeleteData();
protected:
string file_name;
LoadState state;
bool opened;
}
- Large parts of files are separated by strong separators:
- Project use Doxygen application for generating documentation. Each file contains this header:
/**
@file filename.h
@ingroup Module_Name
@author Your Name
@date Year
@version 1.0 - Initial.
@version 1.1 - Changes made...
*/
- Functions are separated by empty lines to blocks. Block can have its own short comment. Don't be shy to use empty lines. Block longer that 20 lines is suspected.
- All variables used in functions (local or parameters) should be checked by 'Assert' macro. If crashes on wrong input are not desired, parameters must be checked by 'if' statement and wrong input should by logged as an 'Error'. Log information can contain additional information. For example if value of input parameter is not valid, this value may be printed to log file.
Where to use Assert: at first everywhere, afterwards asserts can be changed to 'if' statements Where not to use Assert: when you want to check parameters that depends on user input (configuration fiels).
Please consider that Assert macro is not compiled into Release version. Therefore thay should be used for transfer of internal parameters. Asserts helps you to find bugs. You don't need to thrifty.
- You should to check result values of functions.
Generated on Sat Oct 20 14:47:30 2007 for Dark Oberon by
1.5.3