Coding style is very personal. Every software programmer has developed their own habit of formatting/documenting their source code in their unique way. It is said: "Show me your code, and I shall tell you who you are", and it is true. You can tell a lot about a person by looking at the code he or she has written.
In projects with open source code, there are often large amounts of different persons hacking around the source code, eventually causing the code to become a mix of many different personalities, style and ideas. Such source code is often referred to as spaghetti code, but mainly, its simply un-maintainable and looks bad. Thus it is necessary for any open source project to clearly define a standard way of formatting things, which must be enforced all throughout the project lifetime.
Coding style goes a lot farther than just a way of formatting things. If done correctly, it can greatly enhance the readability of the source code; it can warn the developer when he or she is doing wrong things and much more. Many of the ideas presented in the following sections of this appendix originate from Linux Kernel coding standard (somewhat modified for C++, and added few additional sections), which itself is inspired from ideas by Kernighan and Ritchie.
Tabs are neither 8 characters, nor 4, nor even 2 characters long. Tabs are one character long, the Tabulator character. In the ANSI code set it's set to code 9. Don't use spaces for indention, only use Tabulators. Don't use Tabulators for anything else other than indention.
Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you have been looking at your screen for 20 straight hours, you will find it a lot easier to see how the indentation works if you have large indentations.
Now, some people claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway and should fix your program.
In short, 8-char indents make things easier to read, and have the added benefit of warning you when you're nesting too deep. Heed that warning.
Line length limit is 80 characters. This is calculated using 8-character-long Tab size. There are no excuses for ignoring this limitation.
Rationale: While the historical reason for 80-character line-length limit was ANSI 24x80 terminals, today it enforces the programmer to write more simple code, and avoid deeply nested blocks, which could render the code unreadable.
The opening brace is always placed on the same line. The closing brace is always placed on a separate line, indented to the same level where the block was originally opened. This placement rule affects all constructs, e.g. functions, classes, enums, if/else/switch/for statements. Thus:
class MyClass {
void myFunc(int arg) {
if (arg > 0) {
std::cerr << "Doh" << std::endl;
}
do {
logDebug("Doh");
} while (true);
}
};
As you might have noticed, in case of do/while loop, the while statement is placed following the closing }. This style is used for every similar construct. If the statement following the closing } is part of the block, it should be placed like that, otherwise, it should be placed on the next line.
Due to the line-length limit, sometimes it's neccesery to break longer statements. As a general rule, you should try to break the longer lines into shorter, simpler lines. For example, instead of:
if (m_download->getPartData()->getMetaData()->getLocation().native_file_string()) {
...
}
do:
PartData *pd = m_download->getPartData();
MetaData *md = pd->getMetaData();
if (md->getLocation().native_file_string()) {
...
}
This is obviously more readable, and allows you to do intermediate pointer value checking as well (recommended). However, sometimes it's not possible, or insensical to break things into smaller statements, thus normal brace placement rules shall be used:
class MyClass {
void myFunc() {
logDebug(
boost::format(
"This is a long debug message with arguments:"
" %s %s %s"
) % m_argOne % m_argTwo % m_argThree
);
}
};
Looking at the previous examples, it's not hard to deduct the entire naming rules. Types (classes, enums, structs) start with capital letter, and capitalized each following word. Functions and variables start with lower-case letter, but each next word is still capitalized. Member variables are prefixed by m_, static variables by s_. You should never ever need to use a global variable, but the rule for naming it would be to prefix it with g_.
Function objects (functors, objects that have operator()) are a somewhat grey area. The common sense is to name them according to functions naming scheme, thus:
struct MyFunctor {
operator()() {}
};
MyFunctor myFunc;
boost::signal<void ()> myFunction;
boost::functiom<void (int, bool)> myOtherFunction;
Spaces should be used before and after all operators. Spaces should be used to separate arguments to functions. Spaces should NOT be used near opening/closing (). The only exceptions are when using multiple counters in for-loop, or when saving 1-2 spaces would reduce line-length below the 80-char limit. Don't rely on the latter too much though, it should be used only when it benefits readability. Hence:
int main(int argc, char *argv[]) {
for (unsigned int i = 0,j = 10; i < argc; i++,j--) {
j += atoi(argv[i]);
}
std::vector<std::string> stringlist;
typedef std::vector<std::string>::iterator Iter;
Iter it = stringlist.begin();
while (it != stringlist.end()) {
std::cerr << *i++ << std::endl;
}
return 0;
}
Documenting code is often mistaken for commenting, and left at that. However, documentation is something completely different. While comments give the reader hints on what and why the code does, the idea of documentation is to make it easier for reader to grasp entire big picture of a structure. In C++, (almost) everything is wrapped into classes and declared in headers - that's where the documentation should also be. Comments however, should go to source files, to function definitions. Thus: comment the implementation, but document the interface.
Documentation on its own is good, but not good enough to provide a complete overview of a software package to the reader, and thus several applications have been developed which are capable of extracting documentation from source code, and generate more over-viewable version of the documentation - HTML, LaTEX and similar are common outputs.
HydraNode source code shall be documented in Doxygen JavaDoc style. The specifications of the style are documented on Doxygen homepage.