GlobalObjects
Loading...
Searching...
No Matches
C++ Programming guide for this project

Introduction

In order to facilitate joint development in C++, it makes sense if programming guidelines are followed. Here are the most important guidelines for this C++ project.

Identifier

Uniform rules apply to the individual types of identifiers.
In principle, the English language should be used for all identifiers.

file names

As a rule, each class should be declared in a header file and defined in a source code file (exceptions are template classes, inline methods and structs). Both files get the class name as name.
If several classes are declared in a header file and defined in a source code file, a meaningful module name should be chosen for the files.

C++ file extensions

C++ header files and global type files get the extension .h.
C++ source code files get the extension .cpp.

class names

Class names are always introduced with a capital letter at the beginning.
To signal an assignment to a project or library, a maximum of 3 letters can be used as abbreviations. The first of these must be an uppercase letter and the other two lowercase letters. The following class name starts again with an uppercase letter. The name should be chosen so that the class's job is clear. If it is a name consisting of several words, they should be written individually according to the CamelCase notation with leading capital letters ( e.g. 'GloBaseMaker').
Template classes get a 'T' inserted before their name, after the project or library abbreviation (e.g. 'GloTOndemandSet').
Alternatively, an assignment to a project or to a library can be realized via a namespace. For the designation of the namespace only 3 lowercase letters should be used as an abbreviation (e.g. glo::BaseMaker). However, the repetition of an abbreviation befor the class name should then be avoided.

Attribute names in classes

The attributes of classes are always introduced with a 'm_' (stands for member). This is then followed by a controversial and not entirely consistent marking according to the Hungarian notation followed by a meaningful name that begins with a capital letter (for example, 'm_sApplicationName' for a string).

Note
Static attributes are not marked separately.

Designation of methods in classes

The methods of classes are always introduced with a lowercase letter. Usually a verb should be used which describes the service of the method (e.g. 'loadIconPath'. If the status of a class is to be queried, it has proven to be useful to start the method name with an 'is' or 'has' (e.g. 'isStored' or 'hasConnection'

Note
Static methods are not marked separately.

Global variables

Global variables are always introduced with a 'g_' (stands for global). This is then followed by a controversial and not entirely consistent marking according to the Hungarian notation followed by a meaningful name that begins with a capital letter (e.g. 'g_sGloVersion' for a string).

Local variables in functions and methods

Local variables are always introduced with a 't_' (stands for temporary). This is then followed by a controversial and not entirely consistent marking according to the Hungarian notation followed by a meaningful name starting with a capital letter (e.g. 't_iErr' for a local Int variable).

Parameter designation

Parameters are usually introduced with a controversial and not entirely consistent marking according to the Hungarian notation, followed by a meaningful name starting with a capital letter (e.g. 'eLockMode' for an enum value).

Files

To simplify the search for content, some file types are predefined or suggested.

Classes

As already mentioned under File names. Usually, each class should be declared in a header file and defined in a source code file (exceptions are template classes, inline methods and structs). Both files get the class name as name.
If several classes are declared in a header file and defined in a source code file, a meaningful module name should be chosen.

See also
File names and C++ file extensions C++ "File extensions"

Global project types

The global constants, enumerations and structures are stored in a header file. The name of this file should be the project or library abbreviation with a following 'Types' ( e.g. 'GloTypes').
If constants, enumerations and structures only affect one class, you must always consider whether they belong in the respective classes.

Global error codes

Global error codes for a project are stored in a header file. The name of this file should be the project or library abbreviation with a following 'Errors' ( e.g. 'GloErrors').

To-do list

A ToList 'ToDo.txt' is placed in the respective C ++ project directory. In this to-do list, individual requirements and things still to be done are listed with priority according to the manner of a Scrum backlog.

Formatting

In order to simplify the recognition of content, some formatting is predefined or suggested.

UTF8

Every text file with special characters must be saved in UTF8 format so that the special characters are handled uniformly.

Indentations

Each logical section in the source code should be indented. Indentations are in 2 character increments. This indentation should not be defined as tab characters.

Curly brackets

The characters '{' and '}' always stand alone in a line. Pairs of brackets are always in one column. It is recommended to also bracket single-line statements in '{' and '}'. Example:

int foo::bar( int iValue )
{
int t_iErr = 0;
if ( iValue )
{
t_iErr = this->doSomething( iValue );
}
return t_iErr;
}

Grouping

To support clarity, logical units are divided by comments and interruptions with lines. Example:

...
protected:
//============== Attributes
//-------------------------------------------------------------------------
/*!
\if english
Objectpointer.
\endif
\if german
Zeiger auf Objekt.
\endif
*/
T * m_pT;
//-------------------------------------------------------------------------
/*!
\if english
The reference count.
\endif
\if german
Der Referenzzähler.
\endif
*/
EuSharedPtrRefCount * m_pRefCount;
//-------------------------------------------------------------------------
public:
//============= Constructors, destructor
//-------------------------------------------------------------------------
/*!
\if english
Default constructor can take object.
\param[in] pT Pointer doe object (optional).
\endif
\if german
Standard-Konstruktor kann Objekt übernehmen.
\param[in] pT Zeiger auf Objekt (optional)
\endif
*/
EuSharedPtr(T * pT = NULL);
//-------------------------------------------------------------------------
...

Line length

The line length should not exceed 80 characters. There are cases where this cannot be adhered to.
Recommendations for line breaks if the line length is exceeded.

  • Parameter transfer after a comma. If you do, it is best to transfer all parameters into one column:
    int foo::bar( int iParamName1,
    int iParamName2,
    int iParamName3,
    int iParamName4,
    int iParamName5,
    int iParamName6 )
  • For arithmetic expressions before an operator:
    int iResult = ( ( iParamName1 + iParamName2 + iParamName3 + iParamName4 )
    iParamName5 ) - iParamName6;
  • In the case of an extensive if statement or while and do-while loops:
    if ( ( iParamName1 && iParamName2 )
    || ( iParamName3 && iParamName4 )
    || ( iParamName5 && iParamName6 )
    {
    ...
    }

Declaration of variables

Individual logically related declarations and assignments should be in the same column.

int t_iMyValue1,
t_iMySecondValue;
MyClass * t_pMyClass = 0;
t_iMyValue1 = 0;
t_iMySecondValue = 0;
t_pMyClass = new MyClass();

Comments

Comments and documentation are necessary to keep the source code understandable.
Comments in the source code should be written in English or translated if possible. Block or line comments can be used as required.
The documentation should be available in several languages and meet the requirements of doxygen.

See also
Documentation with doxygen.

Documentation with doxygen

The documentation of the C++ projects is realized with doxygen. Here doxygen is not described as such, but how and where it is used.
If there should be a language-specific documentation, the respective documentation text is enclosed between '\if german' (for german) and '\endif'. For the English language this would be, for example, '\if english' and '\endif'. This should make it possible for every programmer to use the respective OpenSource products or to work on the project, regardless of which language(s) he or she speaks.

Header file

Each header file gets a hint about the license after the include blocker. A short description can be multilingual; the license text is always in English.

Example for class 'GloLocalThread'.

#ifndef INC_GLOLOCALTHREAD_H
#define INC_GLOLOCALTHREAD_H
//-----------------------------------------------------------------------------
/*!
\file GloLocalThread.h
\brief
\if english
Header for GloLocalThread
\endif
\if german
Header für GloLocalThread
\endif
\author Helmut Jakoby
\copyright © 2020 Helmut Jakoby
<!-- @@TermsOfLicense BEGIN -->
<b>Terms of License</b>
This file is part of the GlobalObjects module.
GlobalObjects is free software:
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.
<b>GNU Affero General Public License Usage</b><br>
You can redistribute it and/or modify it under the terms of the GNU Affero
General Public License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version. Please review
the following information to ensure the GNU Affero General Public License
requirements will be met: https://www.gnu.org/licenses/agpl-3.0.en.html .
<!-- @@TermsOfLicense END -->*/
//-----------------------------------------------------------------------------

The file and class name, the author name and copyright entry as well as the project or module name are adjusted.

Classes

The class is described after any necessary forward declarations and includes directly above the class declaration.

Example for template class 'GloTOndemandSet':

...
#include "GloBasePersistent.h"
//-----------------------------------------------------------------------------
/*! \brief
\if english
A type-safe set of references to persistent objects in the database (intended
as an attribute for persistent objects).
Unlike a GloTPointerSet (where the referenced objects are 'loaded'), the
GloTOndemandSet is a set of references to persistent objects using the object
ID. This means that the objects are not loaded from the database with the
referencing object, but can be reloaded if required.
It is always useful when an object references large objects that do not
necessarily have to be available in memory.
\endif
\if german
Ein typsicherer Set von Referenzen auf persistente Objekte in der Datenbank
(gedacht als Attribut für persistente Objekte).
Im Gegensatz zu einem GloTPointerSet (bei dem die referenzierten Objekte
'mitgeladen' werden), ist der GloTOndemandSet ein Set von Referenzen über
die Objekt-ID auf persistente Objekt. Es werden die Objekte also nicht mit
dem referenzierenden Objekt aus der Datenbank geladen, sondern können bei
Bedarf nachgeladen werden
Sinnvoller Einsatz ist immer dann gegeben, wenn ein Objekt große Objekte
referenziert, die nicht im jeden Fall im Speicher verfügbare sein müssen.
\endif
\copyright © 2020 Helmut Jakoby
\author Helmut Jakoby
*/
template < class T > class GloTOndemandSet : public GloOndemandSet
{
...

Attributes

The description text for attributes is described directly in front of it as shown in the example.

Example of an attribute 'GloObjID m_RefObjID':

...
//============== Attribute
//-------------------------------------------------------------------------
/*!
\if english
The reference to a persistent object as object ID.
\endif
\if german
Die Referenz auf ein persistentes Objekt als Objekt-ID.
\endif
*/
GloObjID m_RefObjID;
//-------------------------------------------------------------------------
...

Enumerations

The description text for enumerations is described as shown in the example.

Example 1 for an Enum 'EnWatchStyle':

...
//============== Enums
//---------------------------------------------------------------------
/*!
\if english
What is being observed, an AllSet or an object?
\endif
\if german
Was wird beobachtet, ein AllSet oder ein Objekt?
\endif
*/
enum EnWatchStyle
{
eUNDEF = 0, /*!<
\if english
Undefined.
\endif
\if german
Undefiniert
\endif
*/
eALLSET, /*!<
\if english
An AllSet will be observed
\endif
\if german
Es wird ein AllSet beobachtet
\endif
*/
eOBJECT /*!<
\if english
An object will be observed
\endif
\if german
Es wird ein Objekt beobachtet
\endif
*/
};
...


Example 2 for an Enum 'EnOpenClose':

...
//============== Enums
//-------------------------------------------------------------------------
/*!
\if english
The thread can open or close a database.
\endif
\if german
Der Thread kann eine Datenbank öffnen oder schliessen.
\endif
*/
enum EnOpenClose
{
/*!
\if english
The database will be opened.
\endif
\if german
Die Datenbank wird geöffnet.
\endif
*/
eOpen,
/*!
\if english
The database will be closed.
\endif
\if german
Die Datenbank wird geschlossen.
\endif
*/
eClose
};
...

Functions and methods

The description text for functions and methods is described as shown in the example.

...
//-------------------------------------------------------------------------
/*!
\if english
Inserts a persistent object into the set behind the current position. If
the set objects are locked by the set, the object to be inserted is locked
with the lock mode of the set. If the set objects are observed by the set,
the object to be inserted is observed with the observation mode of the set.
\param[in] spNewObj The persistent object to be inserted in a GloSharedPtr.
\return A return value < 0 indicates an error.
\endif
\if german
Fügt ein persistentes Objekt in die Set hinter der aktuellen Position ein.
Wenn die Setobjekte durch die Set gesperrt sind, wird das einzufügende
Objekt mit den Sperrmodus des Sets gesperrt. Wenn die Setobjekte durch
die Set beobachtet werden, wird das einzufügende Objekt mit den
Beobachtungsmodus des Sets beobachtet.
\param[in] spNewObj Das einzufügende persistente Objekt in einem GloSharedPtr.
\return Ein Rückgabewert < 0 zeigt einen Fehler an.
\endif
*/
virtual int insert( GloSharedPtr<T> spNewObj );
//-------------------------------------------------------------------------
...