MaverickCodestylePolicy

Differences between revisions 2 and 20 (spanning 18 versions)
Revision 2 as of 2010-04-07 23:42:13
Size: 5447
Editor: d-65-175-172-80
Comment:
Revision 20 as of 2010-04-08 00:40:53
Size: 9243
Editor: d-65-175-172-80
Comment:
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
 * '''Contributors''': Jonathan265  * '''Contributors''': Jonathan265, HaraldSitter
Line 17: Line 17:
* Matt is a developer. Matt wishes to start contributing to Kubuntu, and just so happens to have C++ skills. The Kubuntu team is able to direct him to the apps we have written in C++, and Matt is pleasantly surprised at the consistent, readable coding style. Matt goes on to be a coding superstar, thanks to clean [s]living[/s] code.

* Amelia is a developer and core contributor to one of the applications that Kubuntu maintains. Unfortunately, she disappears in a bizarre gardening accident, leaving her project orphaned. Thanks to clean, consistent code, the rest of the Kubuntu is able to properly maintain the application in her abscence.
 * Matt is a developer. Matt wishes to start contributing to Kubuntu, and just so happens to have C++ skills. The Kubuntu team is able to direct him to the apps we have written in C++, and Matt is pleasantly surprised at the consistent, readable coding style. Matt goes on to be a coding superstar, thanks to clean code.

 * Amy is a developer and core contributor to one of the applications that Kubuntu maintains. Unfortunately, she disappears in a bizarre gardening accident, leaving her project orphaned. Thanks to clean, consistent code, the rest of the Kubuntu is able to properly maintain the application in her abscence.
Line 22: Line 22:
* Similar to kdelibs and amarok style, the later being spec'd here: http://gitorious.org/amarok/amarok/blobs/master/HACKING/intro_and_style.txt  * Similar to kdelibs and amarok style, being spec'd here:
http://techbase.kde.org/Policies/Kdelibs_Coding_Style an
d here: http://gitorious.org/amarok/amarok/blobs/master/HACKING/intro_and_style.txt
Line 26: Line 27:
* Spaces, not tabs
* Indentation is 4 spaces
* Lines should be limited to 90 characters
* For pointer and reference variable declarations put a space between the type and the * or & and no space before the variable name.
* For if, else, while and similar statements put the first bracket on the same line as the statement declaration, with the ending bracket lining up to the indentation of the statement declaration
* Function and class definitions have their brackets on separate lines
* A function implementation's return type is on its own line.
* CamelCase.{cpp,h} style file names.
* Qt 4 includes a foreach keyword which makes it very easy to iterate over all elements of a container. Use whenever possible.
 * Spaces, not tabs
 * Indentation is 4 spaces
 * Lines should be limited to 90 characters
 * For pointer and reference variable declarations put a space between the type and the * or & and no space before  the variable name.
 * Declare one variable per line, no more.
 
* For if, else, while and similar statements put the first bracket on the same line as the statement declaration, with the ending bracket lining up to the indentation of the statement declaration
 * Function and class definitions have their brackets on separate lines
 * A function implementation's return type is on its own line.
 * CamelCase.{cpp,h} style file names.
 * Qt 4 includes a foreach keyword which makes it very easy to iterate over all elements of a container. Use whenever possible.
Line 40: Line 42:
        if(list.isEmpty()) {         if (list.isEmpty()) {
Line 44: Line 46:
        /*
         
Define the temporary variable like this to restrict its scope
          when you do not need it outside the loop. Let the compiler
          optimise it.
         */
        
foreach(const QString &string, list) {
            kDebug() << "Current string is " << string << endl;
        // Define the temporary variable like this to restrict its scope
        // when you do not need it outside the loop. Let the compiler
        // optimise it.
        foreach (const QString &string, list) {
            kDebug() << "Current string is: " << string;
Line 56: Line 56:
* Use CamelCase for everything.
* Local variables should start out with a lowercase letter.
* Class names are captialized
* Prefix class member variables with m_, ex. m_trackList.
* Prefix static member variables with s_, ex s_instance
* Functions are named in the Qt style. It's like Java's, without the "get"prefix.
  * A getter is variable()
  * If it's a getter for a boolean, prefix with 'is', so isCondition()
  * A setter is setVariable( arg ).
 * Use CamelCase for everything.
 * Local variables should start out with a lowercase letter.
 * Class names are captialized
 * Prefix class member variables with m_, ex. m_trackList.
 * Prefix static member variables with s_, ex s_instance
 * Functions are named in the Qt style. It's like Java's, without the "get"prefix.
   * A getter is variable()
   * If it's a getter for a boolean, prefix with 'is', so isCondition()
   * A setter is setVariable( arg ).
Line 105: Line 105:
=== Qt Includes ===

If you add #includes for Qt classes, use both the module and class name. This allows library code to be used by applications without excessive compiler include paths.
Example:

{{{
// wrong
#include <QString>
}}}

{{{
// right
#include <QtCore/QString>
}}}

=== Switch statements ===

Case labels are on the same column as the switch

Example:
{{{
switch (myEnum) {
case Value1:
    doSomething();
    break;
case Value2:
    doSomethingElse();
    // fall through
default:
    defaultHandling();
    break;
}
}}}
Line 109: Line 143:
All comments, except for comments being used for doxygen documentation in header files, should use the "//" style comments.
Line 112: Line 148:
/** Due to xine-lib, we have to make K3Process close all fds, otherwise we get "device is busy" messages
  * Used by AmarokProcIO and AmarokProcess, exploiting commSetupDoneC(), a virtual method that
  * happens to be called in the forked process
  * See bug #103750 for more information.
  */
// Due to xine-lib, we have to make K3Process close all fds, otherwise we get "device is busy" messages
// Used by AmarokProcIO and AmarokProcess, exploiting commSetupDoneC(), a virtual method that
// happens to be called in the forked process
// See bug #103750 for more information.
Line 138: Line 173:
virtual bool play( uint offset = 0 ) = 0;
}}}
virtual bool play(uint offset = 0) = 0;
}}}

=== Header Formatting ===
General rules apply here. Please keep header function definitions aligned nicely,
if possible. It helps greatly when looking through the code. Sorted methods,
either by name or by their function (ie, group all related methods together) is
great too. Access levels should be sorted in this order: public, protected, private.

All methods/members must have doxygen-compliant API documentation

{{{
#ifndef AMAROK_QUEUEMANAGER_H
#define AMAROK_QUEUEMANAGER_H

class QueueList : public QListView
{
    Q_OBJECT
    public:
        /*
           Default constructor

           @param parent Parent widget
           @param name Name of the QueueList
        */
        Queuelist(QWidget *parent, const char *name = 0);

        /*
           Default destructor
        */
        ~QueueList();

    public slots:
        /*
           Moves the currently selected item up in our list of
           awesome items. Triggers unicorn happiness
        */
        void moveSelectedUp();

        /*
           Moves the currently selected item down in our list of
           awesome items. Does not trigger unicorn happiness
        */
        void moveSelectedDown();
};

#endif
}}}


=== 0 vs NULL ===
The use of 0 to express a null pointer is preferred over the use of NULL.
0 is not a magic value, it's the defined value of the null pointer in C++.
NULL, on the other hand, is a preprocessor directive (#define) and not only is
it more typing than '0' but preprocessor directives are less elegant.

{{{
    SomeClass *instance = 0;
}}}


=== Const Correctness ===
Try to keep your code const correct. Declare methods const if they don't mutate the object,
and use const variables. It improves safety, and also makes it easier to understand the code.

See: http://www.parashift.com/c++-faq-lite/const-correctness.html

Example:
{{{
bool MyClass::isValidFile(const QString& path) const
{
    const bool valid = QFile::exist(path);

    return valid;
}
}}}

=== Commenting Out Code ===
Don't keep commented out code. It just causes confusion and makes the source
harder to read. Remember, the last revision before your change is always
availabe in Git. Hence no need for leaving cruft in the source.

Wrong:
{{{
myWidget->show();
//myWidget->rise(); //what is this good for?
}}}

Correct:
{{{
myWidget->show();
}}}

=== Tips & Tricks ===
A useful service is http://lxr.kde.org. Lxr is a cross reference of the entire
KDE SVN repository. You can for instance use it to search for example code
from other applications for a given KDElibs method.

=== Copyright/Licensing ===
Please follow the KDE licensing policy: http://techbase.kde.org/Policies/Licensing_Policy

Please note that it is not sufficient to write a pointer to the license (like a URL). The complete license header needs to be written everytime. In addition, the application must ship with a complete copy of each license used.

Summary

This specification defines what the code style for all Kubuntu-specific tools written in C++ should use moving forward.

Rationale

Deciding on a common code style will ensure that our C++-based apps remain readable and maintainable, so that anybody with a sound programming head could jump in on development for any Kubuntu app.

Scope and Use Cases

Use Cases

  • Matt is a developer. Matt wishes to start contributing to Kubuntu, and just so happens to have C++ skills. The Kubuntu team is able to direct him to the apps we have written in C++, and Matt is pleasantly surprised at the consistent, readable coding style. Matt goes on to be a coding superstar, thanks to clean code.
  • Amy is a developer and core contributor to one of the applications that Kubuntu maintains. Unfortunately, she disappears in a bizarre gardening accident, leaving her project orphaned. Thanks to clean, consistent code, the rest of the Kubuntu is able to properly maintain the application in her abscence.

Implementation

  • Similar to kdelibs and amarok style, being spec'd here:

http://techbase.kde.org/Policies/Kdelibs_Coding_Style and here: http://gitorious.org/amarok/amarok/blobs/master/HACKING/intro_and_style.txt

Formatting

  • Spaces, not tabs
  • Indentation is 4 spaces
  • Lines should be limited to 90 characters
  • For pointer and reference variable declarations put a space between the type and the * or & and no space before the variable name.

  • Declare one variable per line, no more.
  • For if, else, while and similar statements put the first bracket on the same line as the statement declaration, with the ending bracket lining up to the indentation of the statement declaration
  • Function and class definitions have their brackets on separate lines
  • A function implementation's return type is on its own line.
  • CamelCase.{cpp,h} style file names.

  • Qt 4 includes a foreach keyword which makes it very easy to iterate over all elements of a container. Use whenever possible.

Example:

bool MyClass::myMethod(QStringList list, const QString &name)
    {
        if (list.isEmpty()) {
            return false;
        }

        // Define the temporary variable like this to restrict its scope
        // when you do not need it outside the loop. Let the compiler
        // optimise it.
        foreach (const QString &string, list) {
            kDebug() << "Current string is: " << string;
        }
}

Class, Function & Variable Naming

  • Use CamelCase for everything.

  • Local variables should start out with a lowercase letter.
  • Class names are captialized
  • Prefix class member variables with m_, ex. m_trackList.
  • Prefix static member variables with s_, ex s_instance
  • Functions are named in the Qt style. It's like Java's, without the "get"prefix.
    • A getter is variable()
    • If it's a getter for a boolean, prefix with 'is', so isCondition()
    • A setter is setVariable( arg ).

Includes

Header includes should be listed in the following order:

  • Own Header
  • Qt includes
  • KDE includes
  • Other library includes, if applicable
  • Own includes

They should also be sorted alphabetically, for ease of locating them. A small comment if applicable is also helpful.

Includes in a header file should be kept to the absolute minimum, as to keep compile times low. This can be achieved by using "forward declarations" instead of includes, like "class QListView;" Forward declarations work for pointers and const references.

TIP: Kate/KDevelop users can sort the headers automatically. Select the lines you want to sort, then Tools -> Filter Selection Through Command -> "sort".

In vim the same can be achieved by marking the block, and then doing ":sort".

Example:

#include "MySuperWidget.h"

#include <QtGui/QGraphicsView>
#include <QtGui/QWidget>

#include <KDialogBase>    //baseclass
#include <KPushButton>    //see function...

#include <otherapi/header.h>

#include "KubuntuLibs.h"
#include "Awesomeness.h"
#include "TardisControls.h"

Qt Includes

If you add #includes for Qt classes, use both the module and class name. This allows library code to be used by applications without excessive compiler include paths. Example:

// wrong
#include <QString>

// right
#include <QtCore/QString>

Switch statements

Case labels are on the same column as the switch

Example:

switch (myEnum) {
case Value1:
    doSomething();
    break;
case Value2:
    doSomethingElse();
    // fall through
default:
    defaultHandling();
    break;
}

Comments

Comment your code. Don't comment what the code does, comment on the purpose of the code. It's good for others reading your code, and ultimately it's good for you too.

All comments, except for comments being used for doxygen documentation in header files, should use the "//" style comments.

Comments are essential when adding a strange hack, like the following example:

// Due to xine-lib, we have to make K3Process close all fds, otherwise we get "device is busy" messages
// Used by AmarokProcIO and AmarokProcess, exploiting commSetupDoneC(), a virtual method that
// happens to be called in the forked process
// See bug #103750 for more information.
class AmarokProcIO : public K3ProcIO
{
    public:
    virtual int commSetupDoneC() {
        const int i = K3ProcIO::commSetupDoneC();
        Amarok::closeOpenFiles(K3ProcIO::out[0],K3ProcIO::in[0],K3ProcIO::err[0]);
        return i;
    }
};

For headers, use the Doxygen syntax. See: http://www.stack.nl/~dimitri/doxygen/

Example:

/**
 * Start playback.
 * @param offset Start playing at @p msec position.
 * @return True for success.
 */
virtual bool play(uint offset = 0) = 0;

Header Formatting

General rules apply here. Please keep header function definitions aligned nicely, if possible. It helps greatly when looking through the code. Sorted methods, either by name or by their function (ie, group all related methods together) is great too. Access levels should be sorted in this order: public, protected, private.

All methods/members must have doxygen-compliant API documentation

#ifndef AMAROK_QUEUEMANAGER_H
#define AMAROK_QUEUEMANAGER_H

class QueueList : public QListView
{
    Q_OBJECT
    public:
        /*
           Default constructor

           @param parent Parent widget
           @param name Name of the QueueList
        */
        Queuelist(QWidget *parent, const char *name = 0);

        /*
           Default destructor
        */
        ~QueueList();

    public slots:
        /*
           Moves the currently selected item up in our list of
           awesome items. Triggers unicorn happiness
        */
        void    moveSelectedUp();

        /*
           Moves the currently selected item down in our list of
           awesome items. Does not trigger unicorn happiness
        */
        void    moveSelectedDown();
};

#endif

0 vs NULL

The use of 0 to express a null pointer is preferred over the use of NULL. 0 is not a magic value, it's the defined value of the null pointer in C++. NULL, on the other hand, is a preprocessor directive (#define) and not only is it more typing than '0' but preprocessor directives are less elegant.

    SomeClass *instance = 0;

Const Correctness

Try to keep your code const correct. Declare methods const if they don't mutate the object, and use const variables. It improves safety, and also makes it easier to understand the code.

See: http://www.parashift.com/c++-faq-lite/const-correctness.html

Example:

bool MyClass::isValidFile(const QString& path) const
{
    const bool valid = QFile::exist(path);

    return valid;
}

Commenting Out Code

Don't keep commented out code. It just causes confusion and makes the source harder to read. Remember, the last revision before your change is always availabe in Git. Hence no need for leaving cruft in the source.

Wrong:

myWidget->show();
//myWidget->rise(); //what is this good for?

Correct:

myWidget->show();

Tips & Tricks

A useful service is http://lxr.kde.org. Lxr is a cross reference of the entire KDE SVN repository. You can for instance use it to search for example code from other applications for a given KDElibs method.

Copyright/Licensing

Please follow the KDE licensing policy: http://techbase.kde.org/Policies/Licensing_Policy

Please note that it is not sufficient to write a pointer to the license (like a URL). The complete license header needs to be written everytime. In addition, the application must ship with a complete copy of each license used.


CategorySpec

Kubuntu/Specs/MaverickCodestylePolicy (last edited 2010-04-14 16:39:50 by 64)