Birth of the style rules
These are the style rules. Setup by the TRoS Development Team (Seniltai and XeryusTC) to enhance readability, and making the coding styles of every programmer in the team synchronous (and the freelancers ofcourse ;)). The style rules are not made to inhibit the creativity or freeness of the programmer, as that will only slow down development and give frustration, instead it is supposed to give a better readability and a better consistency in the code.
Therefore at the creation of this document, the entire team has to agree on a rule unanimously before it will be added to this section to prevent having cumbersome and annoying rules.
Variables
Naming
Variables have a pretty special naming convention in TRoS that hasn't been applied everywhere up to date. There are two kinds of naming conventions on variables depending on the situation.
- The first character of public, global, and parameters are always uppercase, the first character of every consequetive word is also uppercase.
- The first character of a private variable is always lowercase, in contrary to the first character of every consequetive word, which is uppercase.
- There is much debate about the local variable, therefore I decided to remove the local variable as a rule until we are sure what has to be implemented.
Example:
class CFoo
{
public:
int MyPublicVariable;
private:
int myPrivateVariable;
};
extern int MyGlobalVariable;
Functions
Naming
Function names require to be clear and easy to remember. Every word in a function name has to start with a capital character. And never start function names with a number.
Example:
void FunctionNamesLookLikeThis();
Return type and arguments
There is one flaw in the rule that has been applied to variables, which is quite annoying to read. The problem is that when you make a function that returns a pointer, you would normally have to put the asterisk before the function name. See in the next example why this is wrong.
- When a pointer is the return type of a function, it is REQUIRED to put the asterisk after the TYPE, instead of in front of the function name.
Example:
// WRONG:
const char *FunctionNowLooksLikeFunctionPointer(const char *MyData);
// RIGHT:
const char* FunctionNowDoesntLookLikeFunctionPointer(const char *MyData).
Comments
Comment your code well, but not to the point that every single line is commented, because then the commenting itself has an opposite effect of what it is supposed to do: increasing readability.
Naming
Comments are required to have a space after the comment-starter (eg. //, /*, //!<, /*! or //!), and they have to start with a capital.
Example:
// A comment looks like this then
Doxygen crawled pages (header files)
- Use //
- When you want to use special doxygen commands, use a multi-line block.
- Multi-line blocks are done with /*! and */, do it like this:
Example:
/*! My Detailed Description
\author Seniltai
\note It's very cool!
\brief Woot!
*/
Non-Doxygen crawled pages (the others)
- Prefer single-line comments, and use // for them, which should be always placed after the line of code or function that is commented.
Exception 1: There are times when you want to comment on a block of lines, then you must put the comment in front of the block that you are commenting about. - Don't use C-Style comment blocks unless the block is longer than 5 lines (>5), because it looks neater. (comments longer than 5 lines are rare so you dont really have to give it much thought.)
- When you want to disable a piece of code, don't use a C-Style comment block. Use #if 0 and #endif, as this prevents the C-Style comments in the code from clashing with each other.
Note: This should never be uploaded to the repository.
Brackets
- Brackets are always placed on a seperate "private" line.
Exception 1: Inline functions. When inline functions aren't longer than 1 command, you may put them behind the function in the header file. (mostly these small functions are accessors) - When having only one command after an if/for/while block, don't put brackets.
Example:
void FooBar()
{
// Bracket example
while(FooInited == true)
{
if(Foo == "Bar")
{
}
}
switch(Foo)
{
case "Foo":
puts("Bar");
break;
case "Bar":
puts("Foo");
break;
}
}
Example:
if (inited)
return false;
while (i < 10)
i++;
for(int i=0; i < 10; i++)
printf("%d", i);
Classes/Structs
Naming
- Classes or structs always start with a 'C' so we know it is one, not using 'C' as a prefix can lead to confusion with typedefs or other types and can lead to confusing which we had encountered in the past.
- Using class is preferred over struct. Structs are commonly used for a class that only has public members, which mostly store data.
Example:
class CClassesLookLikeThis { };
Declaration
- Place public: before private: and protected: always comes last, This is again done to prevent confusion.
- Constructors, copy-constructors and destructors are always the first functions in the public: section if they're used.
- Functions are always sorted to function first, then return type. It doesn't have to be alphabetic though, just group them.
- Classes and/or structs in Sawan (TRoS Engine) need the headerfile PreProcessor.h included, every function/struct/class/global/enum variable need to have the preprocessor define, TROSAPI after the class/struct/(return type) keyword.
Example:
void TROSAPI MyGlobalFunction();
extern TROSAPI int MyGlobalVariable;
TROSAPI int MyGlobalVariable;
enum TROSAPI MyEnum;
class TROSAPI CMyClass
{
public:
void MySpiffyFunction(); // Note: In the functions inside the classes you don't need TROSAPI after void.
private:
int mySpiffyVariable; // Note: Same goes for variables or anything else in the class/struct.
}; // structs work exactly the same like a class, the only difference is that class has to be renamed into struct ;)
Enumerations
Naming
- Enums and their members are fully uppercase with underscores between the individual words.
- Use enum instead of define because the compiler does most of the work for you.
- Anonymous enums are explicitly forbidden, as they clutter the namespace.
Example:
enum ENUM_NAMES_LOOK_LIKE_THIS {};
Indexing
- Indexes are allowed, but only at the first entry, as there are some cases you want to start the enum at the beginning of another enum (see TrosPackets.h and PacketEnumerations.h) or start at 1 instead of 0 (see Logging.h).
- Place a comma at the last item in the enum except if the last item is used for counting the total items in the enum.
- Item counters are named as NUM_ENUM_NAME (or the plural form if possible).
Example:
enum FOO
{
FOO,
BAR,
};
Example:
enum BAR
{
FOO,
BAR,
NUM_BARS,
};
Enumerations
- Standard headers(
) are defined before non-standard headers("header.h"). - Use const and static as much as possible.
- Tab size is equal to 4 spaces, but never use spaces as indentation, try to configure it in your preferable editor (when your application shows 8 "spaces" per tab, like DoxyGen, it will be 4 in the rest of the applications).
- Try avoiding long lists of if's by putting them into multiple functions. An array of Functors (Callback.h in the TRoS Engine) or regular function pointers might be of use here.
- Try to teach yourself to use a space after for, if, switch and while. It is not required because everyone does this differently, but if we all do the same it will be much better, though there are some cases that this method is less clear.
- Put a space before and after binary operators: (i == 1) && (j == 2), (i == 1) || (j == 2), etc.
- Add an extra empty line to the bottom of the file, some compilers give a warning if there isn't an empty line at the end of the file.
- Try to remove as much warnings as possible before commiting, some compilers show errors where others just show warnings.