Coding styleguide for the qmwedit project
 

Tabel of Contens

 
 
1. Intruduction
1.1 What is a coding standard?
1.2 It's natural
1.3 Practical example
1.4 Files
2. Basic conventions
2.1 Macros
2.2 Indentation
2.3 Bracket placement
2.4 Parentheses, brackets and comma
2.5 If statements and while loops
3. What remains
3.1 Naming conventions
3.2 Functions
3.3 Name spaces
3.4 Classes
3.5 Comments
3.6 Exceptions
 
 
 
 

1.Intruduction

First at all I would like to thank Gunnstein Lye. He his the author of the originale style-guide. It is a good one to use it in opensource projects. For our project I was so free to add some extras and remove some . The rest of document is the same like at zez.org. Coding standards define a standard for the look and feel of your code. This is helpful to most projects, and to some it is a necessity. Especially in open source projects. The goal of this articles is to show how coding standards will improve a development project.

 
 
1.1 What is a coding standard?

A coding standard is a set of rules describing how your code should look, which features of the  programming language you will use and how, and possibly which tools should be used to write the code. It can of course be as specific as you want it to be. Why is it good?

People are different. We like different things, wear different clothes, and use different styles when coding. This is fine as long as we just write small programs and scripts for ourselves. When many people

collaborate on a project, the differences in coding style will lead to disagreements and poor readability which will hamper the cooperation and thereby the effectiveness of the project. An example of such disagreements is the simple, but widespread problem of indentation. How much indentation should be used? Where? Should we use spaces or tabs? There are probably as many opinions on this as there are programmers, and most of them are dead sure that their way is the right one. (The correct way of indenting C++ code is 3 or 4 spaces per level and no tabs, if you were curious. And, by the way, keep those curly brackets on a separate line, or you'll face at least seven years of bad luck and core dumps.) These problems are obvious in many open source projects where perhaps hundreds of people from all around the world develop software together, but it will soon become a problem in small projects and corporate environments as well. Even when you just write your own programs you will run into difficulties sooner or later, unless you use some kind of coding standard.

1.2 It's natural
 

Your personal taste in programming is in itself a coding standard. You don't randomly use constants with upper and lower case, you probably don't mix different styles of while-loops and you definitely don't use a different indentation for each line of code. (At least I hope you don't, for your own sanity's sake.) Standards are natural. Unfortunately, arguing about them is, too. Always remember, when you join an open source project it is common sense to follow that project's standards. If you try to force your standards on others you'll lose your write privileges faster than fast. That's one of the great advantages of starting a project, you get to do it the right way - your way.
 

1.3 Practical example
 

I'll try not to talk too much about how great this standard is (it is of course the best possible standard, but, as I said, I'll try not to talk too much about that) but rather to stress the importance of having standards at all. Almost any standard is better than no standard. And again, this is a C++ example, but the principles and concepts here are valid for many, if not most programming languages.

1.4 Files
 

All filenames are lowercase. Header files are suffixed with .hpp, implementation files with .cpp. The advantages of using all lowercase filenames on a case-sensitive system like Linux is obvious. The use of the .hpp suffix enables us to differ between C and C++ header files. Each cpp/hpp pair contains only one class, unless we are using private classes. If a header file contains constants and declarations that don't need external includes, as well as other declarations that do need external includes, then dividing this file to avoid too many dependencies could be a good idea. An implementation file that has to be written differently for different platforms, is to be split into one file containing platform-independent code, and one file per platform containing platform-dependent code. All #include<> should be sorted from A to Z. Below of that kind of includes you can list the #include""  in the same  order like the others.

The header of each file should contain a couple of importend information like:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Programm: This class handels the tabbar (e.g. paint, repaint, add/del tab)
//File: tabbar.h
//Author: Juergen P. Messerer
//Date(dd.mm.yy): 3.2.1999
//License:
//Revision:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 

2. Basic conventions

2.1 Macros

Macros and other # commands are to be avoided. Exceptions are #include and the necessary #ifndef, #define, #endif in header files. Macros can be used when there are good reasons to do so, though.
 

2.2 Indentation
 

Use 3 or 4 character indentation, this is commonly used and allows for easy recognition of the indentation level. Use spaces in stead of TABs, to assure the code looks the same every-where.

2.3 Bracket placement

Put begin and end brackets {} on the same column, and on the same column as the statement that "owns" the brackets.

 

  Example :
 
int meaning( int x, int y )
{
    if( x == y )
   {
        ..
   }
   else
  {
       if( x > y )
      {
          ...
      }
      else
      {
         ...
      }
   }
   return42;
}
 
 

2.4 Parentheses, brackets and comma

 
Use a space after every comma. Use a space after a begin parenthesis, and a space before an end parenthesis. Do not use such spaces for square brackets. Use one, and only one space between each type. Put pointer * and reference & signs adjacent to the variable they belong to.
Use empty lines to group variables and codelines that logically belongs together. Variable names that are grouped this way must be on the same column. Empty lines must be empty, containing no Tabs or spaces. If you are unsure of the execution order of an expression, use more than the minimum required number of parentheses and remove them when it becomes more clear.
 
2.5 If statements and while loops
 

Nested if statements must use brackets {}. If you have many consecutive if and else if statements, consider using case statements instead, or redesign using a more object oriented approach. If statements and while loops can only execute boolean expressions, never assign or change any data.

The next part of this article will be a bit longer and more advanced, as I'll advance to topics such as naming conventions, functions, classes and namespaces.

 

3. What remains

3.1 Naming conventions

All names must be written in English, and be grammatically correct. Avoid names that don't mean anything, like foo and tmp. Any numbers in a name must be written using letters, not numbers, unless there is a good reason not to.

 

 
ValueOne
 

Functions can be made up from several words, the first letter of each word in uppercase and the rest in lowercase. The first word must be all lowercase. Acronyms should not be used.

 
 
void
setText( const QString &r_text );
 

 

Pointers should start with a p_ and references with r_.
 

 
int*p_myPointer;
char&r_yourReferenc;
 

Constants are written in uppercase, multiple words divided by underscore.
 

 
const float PI
=3.1415;
const int MAGIC_NUMBER =42;
 

Enumerators and member variables can be made up from several words, the first letter of each word in uppercase and the rest in lowercase. They should normally not consist of more than three words. Acronyms can be used as long as the meaning is obvious.

 

enum DayType
{
    Monday,
   Tuesday,
    ...
};
 
 
 
private:
int Len;
int X,Y;
 

Local variables can consist of several words, using only lowercase. Use underscore to divide words. Use as few words as possible, and use acronyms when needed. Special acronyms like i (index) and x,y (position) are allowed. Parameters should be named in the same way as local variables.

 
 
 
int
i, index, x, y;
int x_add;
 

Class names can be made up from several words, the first letter of each word in uppercase and the rest in lowercase.
 

 
class
Dialog;
lass ModuleManager;
 

Static variables should be named like member variables, but they must end with an underscore.
 

 
static int refCount;
double myMember_; //Membervariable of a class
char *m_alsoMember; //Membervariable of a class
 

Never use global variables, put them in a class and make them static.
 
 

3.2 Functions

All functions must be placed inside classes. Exceptions are main() and functions used as an interface between classes and a C-API. Functions should be short and do one task. The length of the function depends on how complex it is. The more complex the function is, the shorter it should be. Too long functions should be split into several functions each doing a minor task. A function should not be longer than 30-40 lines. Use variables sparingly, split the function when you have too many. If the function is clearly divided into different parts you may use more variables, but no more than 7 per block of code. Exceptions to this rule are certain mathematical calculations where speed is essential. If a function has many parameters it might be wise to split the parameter line into several lines, place the parameters with a close relation to each other on the same line. Many parameters is often a sign that your function is too big, try splitting it. Try to make functions const as often as possible. Avoid inline code, but when you do use it, try to post phone it until the class is considered done. This is to avoid massive recompiling due to dependencies. Be careful with default values for function parameters, try to specify everything as explicitly as possible. For optical reason it is better to put a comment line between each implementation of the functions.

 

}
//---------------------------------------------------------------
void MyClass::function()
{
 
 
 

3.3 Name spaces

In order to avoid bad or too long class names, use name spaces to split and ground classes and functions. This means that two classes can have the same name as long as they exist in different name spaces, enabling you the use more intuitive names. However, before you start using name spaces make sure it will work on all platforms used in the project.
 

3.4 Classes
 

Classes should do only one thing and do it well. Split it into subclasses if it's too big. Use multiple inheritance sparingly, consider using a pointer to an object (this is often called composition) instead of inheriting it. All member variables must be private. When access to member variables is required use functions, never use public or protected variables.

Helper functions should be private. Functions that don't access member variables or functions can be made static.
 

3.5 Comments
 

For every function, write a comment that explain what it does, and any hard-to-understand parameters. These comments should be written in Doxygen syntax. Also write a comment on a class' area of responsibility. Use a newline between comments and functions. Don't over comment your code, use comments when needed. If you have to put lots of comments in your code to make it readable, it's a sign that it is badly written and should be redone.
 

3.6 Exceptions
 

Use exceptions to control things that don't work as they were expected to, like parameters having values they should never have. Use them often. Don't use exceptions as a way of leaving loops or nested function calls, or signalling an expected outcome. Be aware of memory leaks that may happen when using exceptions. (The book "The C++ Programming Language" by Bjarne Stroustrup has comments on this.) Functions that use exceptions should explicitly state so in the documentation. When using a function with exceptions, always use a try/catch statement to handle it. Use a try/catch statement in main() to tell the user/developer of any fatal errors that happens.