Coding Standards

From MythTV Official Wiki
Revision as of 20:32, 9 January 2008 by Gsgleason (Talk | contribs)

Jump to: navigation, search

Coding Standards

The rules of thumb on this page are meant to help developers ensure that their code fits in with the normal conventions in the MythTV source. These standards are mostly voluntary, and there's plenty of existing code that doesn't follow these standards, but you can more easily produce readable and understandable code if you keep these items in mind.

For more of an overview of the development process for Myth, see the MythTv Development How To or MythPlugin Architecture.

Spaces and braces

The one hard and fast rule of Myth development: don't use tab characters.

Indents are accomplished with 4 spaces. Please set your editor to convert tabs to spaces, or at least do the conversion before you submit a patch.

You should put 1 space between keywords like if or for and their parenthesized lists. By contrast, don't do the same for function names; there should be no space between the name and its opening parenthesis. There should be no spacing between parentheses and the items they contain.

Spaces are used between binary operators (meaning + or =).

Braces should go on their own line. The exception to this is the declaration of structs or enums, where the opening brace goes on the same line as the type declaration. One-line if or else bodies do not need braces.

Lines should not exceed 80 characters in width. If you have a long statement, indent the continuations so they line up vertically. Generally, if you indent past the last opening parenthesis of the previous line, you'll be in good shape.

enum MyEnum {
    TEST_ONE,
    TEST_TWO,
    TEST_THREE
};

static inline void runThreeTimes(QStringList strings,
                                                  char *buffer)
{
    for (int i = 0; i < 3; i++)
    {
        result = MyFunc(i, strings);
        if (result == TEST_ONE ||
            result == TEST_THREE)
        {
            DoSomething();
            DoMore();
        }
        else
            DoTheOpposite();
    }
}

For Vi(m) users: the following options can be put into your ~/.vimrc file -

set expandtab
set tabstop=4
set shiftwidth=4

And if it's not too intrusive, this line can appear in the source code, and Vim will apply the correct settings:

/* vim: set expandtab tabstop=4 shiftwidth=4: */

Class and variable names

Class names and enum names are written in StudlyCaps, with an initial capital letter and no underscores. Methods are StudlyCaps, or lowerWithCaps. Variable names are all lowercase, or lowerWithCaps. Member variables in classes are usually prefixed with "m_". Constants should be written with a "k" prefix and inner caps; the few global variables use a "g" prefix. Enum values should be written in ALL_CAPS with underscores. Hungarian notation is not generally used outside of Windows code.

Make your variable names left-to-right specific. Related variables should sort together alphabetically; audioId and audioMutex should stand apart from videoTimeRemaining. The names should be compact, but be as self-explanatory as possible.

const int kAudioBuffers = 32;
enum AudioChannels {
    CHANNEL_LEFT  = 0x01,
    CHANNEL_RIGHT = 0x02,
    CHANNEL_ALL   = 0xff
};

class AudioOutput
{
public:
    // Adjust the volume by a delta, from +100 to -100.
    void adjustVolume(int change);
protected:
    // The absolute volume, from 0-100.
    int m_volume;
}

Comments

Comments should be compact; you should spend your time making your code readable and your variable names self-explanatory. Comments should give necessary overviews of functionality, or document strange cases, ranges, etc.

Description of variables' use and purpose should accompany the declaration. For class variables, a rough outline of how they fit into the algorithm should be given and any assumptions or notes on valid ranges should be given.

The majority of your comments should be in header files, where the public interface to functionality is exposed. If your design is reasonable and straightforward, you shouldn't have much that needs explaining in the .cpp file.

Doxygen comments are accepted in the code, but you must keep them brief -- a few lines maximum. Again, don't add redundant information.

Design guidelines

There's more to programming than typing; here's some advice to keep in mind while designing or updating code:

  • Use C++. There's a collection of tips to avoid outdated C constructs. Myth supports gcc 2.95.x and above.
  • Use Qt for non-GUI tasks. Don't design your own helper classes or use platform-dependent code when Qt already offers a class. Strings, lists, and mutexes are good examples of Qt's generic functionality. Myth supports Qt 3.3, so check your calls against the Qt 3.3 documentation so you don't break things. There is a branch dedicated to porting Myth to QT 4 at mythtv-qt4
  • Use Myth for GUI tasks. Isaac is currently working on a UI layer that's independent of Qt, and patches that use native Qt widgets or extend the Myth wrappers around the Qt GUI will be rejected. Use the existing items in mythwidgets.h and elsewhere to accomplish your GUI goals.
  • Stay platform-independent. Use Qt instead of #ifdefs where possible. If you must add something that only works on one platform, add a compile-time flag so that it's only built where it works. See settings.pro for several examples.
  • Avoid dependencies. Dependencies are added very rarely to Myth, so think carefully before you suggest a new item. If you want to link to a library that's small and has unique functionality, you may be able to get it added to the core Myth build. In general, though, avoid external dependencies if at all possible.
  • Use private classes to keep header files stable. This design pattern is used in Myth Context and others; most of the private data and methods are stored in a private class, defined in the .cpp file. A pointer to this class is stored as a member variable in the public class. This way, the private data can change without changing the header file, which prevents everyone from having to rebuild most of the source tree for a popular header like mythcontext.h.
  • Don't use assert() Crashing is never good. Use proper error handling in place of assert.