Coding Conventions for the KOM(S) Streaming System This document describes the preferred coding style when changing and/or extending komssys. Many developers contributed code to komssys over the time, due to this fact the code has become quite inconsistent which makes it difficult to read and to change. A lot of komssys code was written before namespaces and the standard template library (STL) were part of C++. In order to achieve better maintainability any newly written code should follow these guidelines. Section 1: Naming Some classes start with the prefix "MN", don't use it in newly written classes, in fact you shouldn't use class prefixes at all, use namespaces instead. The Naming conventions you should stick to are pretty much the same as Sun's Java Naming Conventions. That means in detail: - Class names should be nouns, in mixed case with the first letter of each internal word capitalized, e. g. "class ProxyServer". - Function names should be verbs with the same syntax as class names except the first letter always being lowercase, e. g. "int getClientCount()". - Member variables should start with an underscore and the next letter in lowercase, e. g. "int _clientCount". - Local variables should look like member variables but without the underscore, e. g. "int tmp". - Constants are written all uppercase letters with underscores delimiting the distinct words, e. g. "const int MAX_VALUE = 64". Section 2: Indentation and placing of braces Indentation width should be 4 spaces. Following is a short example of how code should look like. It also shows how curly braces should be placed, that is to say every brace on its own line. class Foo { public: int getCount(); Foo* doSomething(Foo* aFoo); private: int _count; }; int Foo::getCount() { return _count; } Foo* Foo::doSomething(Foo* aFoo) { if (aFoo == this) { _count++; return this; } for (int i = 0; i < _count; ++i) { doWhatever(aFoo); doMore(); } return aFoo; } Section 3: Comments You should at least comment class and function declarations unless the purpose is really obvious. That means in front of every class and function should be an comment block describing the purpose of it. The emphasis should be placed on what a class or function does, not how. These comments should be in the corresponding header files, preferably using doxygen style. Inside functions you can comment blocks of code using normal C++ style comments, but don't overdo it. Too many comments inside functions make the code harder to read and sometimes even hint at bad code. Most of the time it's better to extract complicated code into its own function with a meaningful name instead of writing a comment. Following is a commented class declaration as an example: /*! * The Foo class maintains connections from and to the * proxy server. For the establishment of these connections * see Bar class. */ class Foo { public: /*! This function must be called directly after the constructor * and before any other member function */ void initializeSockets(); /*! Responsible to start something */ int startSending(); private: /*! container to keep the sockets */ std::vector<int> _connections; }; Section 4: Macros Simple rule: Avoid them. If you want to define constants use the const qualifier or enum instead of #define. Especially the NULL macro for pointers is frowned upon in C++, use 0 or 0x0 if you want to emphasize that it's a pointer. One exception to this rule are include guards, which you should use in every header file to avoid conflicts when included multiple times, e. g. ServerGM.h looks like this: #ifndef SERVER_GM_H #define SERVER_GM_H /* ...contents... */ #endif Section 5: General Programming Practices Komssys is a large software project. Without the aid of an IDE you will probably get lost in the complexity. So do yourself a favor and get used to one. If you don't know any IDEs try kdevelop or eclipse with CDT plugin. Avoid public methods that return pointers or references to private member variables; if you think you really have to do that, at least make the return value const. Unfortunately this violation of the encapsulation principle is quite common in current komssys code. The severe disadvantage of this is that it leads to almost unmaintainable code, because changes to the private member variable almost always force you to change every caller (which can be a lot) of the method which returns the pointer or reference. There are a number of container classes in komssys which are very similar to classes in the Standard Template Library (STL) which is part of the C++ language standard. They stem from libg++, which was included with gcc before STL. Most notably are the classes MNString and MNList. Use std::list in newly written code instead of MNList, because the handling of std::list is more intuitive and it's easier to read for people not used to the komssys code. MNString on the other hand is so prevalent in komssys code that it makes no sense to use std::string instead. As a general rule, prefer STL classes and algorithms over self written code. Functions should be preferably short to increase chances of code reuse. Withstand the urge to copy and paste and extract code into its own function instead of duplicating it, it leads to much better code. Think twice before you define a function inline. Most of the time you will be writing code that is not performance critical, so inlining will most likely do more harm than good, because it makes debugging much harder. If you notice that a switch statement you are writing becomes longer and longer you should check if class inheritance and virtual functions are an appropriate alternative. Maybe the state or strategy design patterns are helpful as well. Section 6: Helpful literature Stroustrup: The C++ Programming Language {The definite reference regarding C++ details but not an easy read for beginners} Meyers: Effective C++; More Effective C++ {Recommendable to every C++ programmer. Very helpful guidelines and easy to understand even for beginners} Gamma et al: Design Patterns {Very helpful with regard to object oriented software design}