ferencd@0: This file contains coding guidelines for VMime. You should follow them ferencd@0: if you want to contribute to VMime. The rules below are not guidelines ferencd@0: or recommendations, but strict rules. ferencd@0: ferencd@0: ferencd@0: 1. General rules ferencd@0: 1.1. Language ferencd@0: 1.2. Unit tests ferencd@0: 1.3. Version Control ferencd@0: 1.4. ChangeLog ferencd@0: 1.5. Warnings ferencd@0: 2. Style, indentation and braces ferencd@0: 2.1. Indentation ferencd@0: 2.2. Brace position ferencd@0: 2.3. "switch" statement ferencd@0: 2.4. Single instruction ferencd@0: 2.5. Line length ferencd@0: 2.6. Spaces and parentheses ferencd@0: 2.7. End-of-line character ferencd@0: 2.8. Short functions ferencd@0: 2.9. Limit Variable Scope ferencd@0: 3. Naming conventions ferencd@0: 3.1. Classes ferencd@0: 3.2. Variables/parameters/member variables ferencd@0: 3.3. Member variables ferencd@0: 3.4. Files ferencd@0: 3.5. Namespaces ferencd@0: 3.6. Constants ferencd@0: 4. Comments ferencd@0: 5. Miscellaneous ferencd@0: ferencd@0: ferencd@0: ferencd@0: 1. General rules ferencd@0: ================ ferencd@0: ferencd@0: 1.1. Language ferencd@0: ------------- ferencd@0: ferencd@0: The project language is English. All comments, variable names, class names, ferencd@0: commit messages and so on, must be in English. ferencd@0: ferencd@0: ferencd@0: 1.2. Unit tests ferencd@0: --------------- ferencd@0: ferencd@0: Unit tests are very important. For each new class you write, you should also ferencd@0: write a unit test for it. If you write a new method, add a new test case in ferencd@0: the unit test of the class. ferencd@0: ferencd@0: When you fix a bug, also add a new test case to ensure the bug will not ferencd@0: happen anymore. ferencd@0: ferencd@0: ferencd@0: 1.3. Version Control ferencd@0: -------------------- ferencd@0: ferencd@0: Each commit MUST be done with a message ('-m' flag) that briefly describes what ferencd@0: changes have been done. ferencd@0: ferencd@0: DO NOT use commit messages like -m "Updated"! ferencd@0: ferencd@0: ferencd@0: 1.4. ChangeLog ferencd@0: -------------- ferencd@0: ferencd@0: ChangeLog must be updated when a major change has occured. It is not required ferencd@0: (but not forbidden) to report minor bug fixes in the ChangeLog. ferencd@0: ferencd@0: Each ChangeLog entry must have an author and a date. ferencd@0: ferencd@0: ferencd@0: 1.5. Warnings ferencd@0: ------------- ferencd@0: ferencd@0: The code should compile WITHOUT ANY WARNING, even those for unused parameters! ferencd@0: ferencd@0: ferencd@0: ferencd@0: 2. Style, indentation and braces ferencd@0: ================================ ferencd@0: ferencd@0: 2.1. Indentation ferencd@0: ---------------- ferencd@0: ferencd@0: Use TABS (ASCII character #9) and _not_ SPACES. This allow everyone to set tab ferencd@0: width to its preferred settings (eg. 4 or 8 spaces). ferencd@0: ferencd@0: ferencd@0: 2.2. Brace position ferencd@0: ------------------- ferencd@0: ferencd@0: Open braces should always be at the beginning of the line after the statement ferencd@0: that begins the block. Contents of the brace should be indented by 1 tab. ferencd@0: ferencd@0: if (expr) ferencd@0: { ferencd@0: do_something(); ferencd@0: do_another_thing(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: do_something_else(); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: 2.3. "switch" statement ferencd@0: ----------------------- ferencd@0: ferencd@0: switch (expr) ferencd@0: { ferencd@0: case 0: ferencd@0: ferencd@0: something; ferencd@0: break; ferencd@0: ferencd@0: case 1: ferencd@0: ferencd@0: something_else; ferencd@0: break; ferencd@0: ferencd@0: case 2: ferencd@0: { ferencd@0: int var = 42; ferencd@0: another_thing; ferencd@0: break; ferencd@0: } ferencd@0: ferencd@0: } ferencd@0: ferencd@0: ferencd@0: 2.4. Single instruction ferencd@0: ----------------------- ferencd@0: ferencd@0: Omit braces around simple single-statement body: ferencd@0: ferencd@0: if (...) ferencd@0: something; ferencd@0: ferencd@0: and not: ferencd@0: ferencd@0: if (...) ferencd@0: { ferencd@0: something; ferencd@0: } ferencd@0: ferencd@0: Except when body spans over multiple lines: ferencd@0: ferencd@0: if (...) ferencd@0: { ferencd@0: something_too_long_for( ferencd@0: a_single_line); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: 2.5. Line length ferencd@0: ---------------- ferencd@0: ferencd@0: Each line of text should not exceed 80 characters. ferencd@0: ferencd@0: Exception: if a comment line contains an example command or a literal URL ferencd@0: longer than 100 characters, that line may be longer than 100 characters ferencd@0: for ease of cut and paste. ferencd@0: ferencd@0: ferencd@0: 2.6. Spaces and parentheses ferencd@0: --------------------------- ferencd@0: ferencd@0: Put spaces around operators: =, >, <, !=, +, -, /, *, ^, %, ||, &&, &, |: ferencd@0: ferencd@0: x = (a * (b + (c - d))) ferencd@0: ferencd@0: Do not put spaces around parentheses. ferencd@0: ferencd@0: if ((a == b) || (c == d)) ferencd@0: ferencd@0: Do not put spaces around "->": ferencd@0: ferencd@0: object->method() ferencd@0: ferencd@0: Do not put spaces inside brackets: ferencd@0: ferencd@0: x = array[index] and _NOT_: x = array[ index ] ferencd@0: ferencd@0: Do not use space between a function name and parenthesis. No extra spaces ferencd@0: between parameters and arguments, just after commas: ferencd@0: ferencd@0: method(arg1, arg2, ...) ferencd@0: ferencd@0: Do use a single space before flow control statements: ferencd@0: ferencd@0: while (x == y) and _NOT_: while(x==y) ferencd@0: ferencd@0: ferencd@0: 2.7. End-of-line character ferencd@0: -------------------------- ferencd@0: ferencd@0: Configure your editor to use "\n" (UNIX convention) for end-of-line sequence, ferencd@0: and not "\r\n" (Windows), nor "\n\r", nor any other combination. ferencd@0: ferencd@0: ferencd@0: 2.8. Short functions ferencd@0: -------------------- ferencd@0: ferencd@0: To the extent that it is feasible, functions should be kept small and focused. ferencd@0: It is, however, recognized that long functions are sometimes appropriate, so no ferencd@0: hard limit is placed on method length. If a function exceeds 40 lines or so, ferencd@0: think about whether it can be broken up without harming the structure of the ferencd@0: program. ferencd@0: ferencd@0: ferencd@0: 2.9. Limit Variable Scope ferencd@0: ------------------------- ferencd@0: ferencd@0: The scope of local variables should be kept to a minimum. By doing so, you ferencd@0: increase the readability and maintainability of your code and reduce the ferencd@0: likelihood of error. Each variable should be declared in the innermost block ferencd@0: that encloses all uses of the variable. ferencd@0: ferencd@0: Local variables should be declared at the point they are first used. Nearly ferencd@0: every local variable declaration should contain an initializer. If you don't ferencd@0: yet have enough information to initialize a variable sensibly, you should ferencd@0: postpone the declaration until you do. ferencd@0: ferencd@0: ferencd@0: ferencd@0: 3. Naming conventions ferencd@0: ===================== ferencd@0: ferencd@0: 3.1. Classes ferencd@0: ------------ ferencd@0: ferencd@0: Classes names are in lower-case. However, each word should start with an ferencd@0: upper-case letter. ferencd@0: ferencd@0: Examples: "object", "exampleClass", "anotherExampleClass"... ferencd@0: ferencd@0: ferencd@0: 3.2. Variables/parameters/member variables ferencd@0: ------------------------------------------ ferencd@0: ferencd@0: Variable names should be enough explicit so that someone reading the code can ferencd@0: instantly understand what the variable contains and is used for. ferencd@0: ferencd@0: Variables names are in lower-case. ferencd@0: ferencd@0: DO NOT use Hungarian notation. ferencd@0: ferencd@0: Examples: "address", "recipientMailbox", ... ferencd@0: ferencd@0: Avoid variable names with less than 5 characters, except for loop indices and ferencd@0: iterators. ferencd@0: ferencd@0: NOTE: variable names like "it", "jt" and so on are commonly used when iterating ferencd@0: over STL containers. ferencd@0: ferencd@0: ferencd@0: 3.3. Member variables ferencd@0: --------------------- ferencd@0: ferencd@0: Use a prefix for class members: "m_" for normal class members, and "sm_" for ferencd@0: static members, if they are not public. ferencd@0: ferencd@0: Examples: "m_mailboxList", "sm_instance"... ferencd@0: ferencd@0: ferencd@0: 3.4. Files ferencd@0: ---------- ferencd@0: ferencd@0: Use ".hpp" for header files, and ".cpp" for implementation files. ".inc" should ferencd@0: be used for implementation files not directly compiled, but included from ferencd@0: other implementation files. ferencd@0: ferencd@0: Files have to be named exactly like the class they define. For example, class ferencd@0: "mailboxList" should be declared in "mailboxList.hpp" and implemented in ferencd@0: "mailboxList.cpp". ferencd@0: ferencd@0: Both header and implementation files must be placed in 'src/vmime/' directory. ferencd@0: ferencd@0: ferencd@0: 3.5. Namespaces ferencd@0: --------------- ferencd@0: ferencd@0: Namespaces are named exactly like variables. ferencd@0: ferencd@0: ferencd@0: 3.6. Constants ferencd@0: -------------- ferencd@0: ferencd@0: Constants are ALL_CAPS_WITH_UNDERSCORES. ferencd@0: ferencd@0: ferencd@0: ferencd@0: 4. Comments ferencd@0: =========== ferencd@0: ferencd@0: The // (two slashes) style of comment tags should be used in most situations. ferencd@0: Where ever possible, place comments above the code instead of beside it. ferencd@0: ferencd@0: Comments can be placed at the end of a line when one or more spaces follow. ferencd@0: Tabs should NOT be used to indent at the end of a line: ferencd@0: ferencd@0: class myClass ferencd@0: { ferencd@0: private: ferencd@0: ferencd@0: int m_member1; // first member ferencd@0: int m_secondMember; // second member ferencd@0: }; ferencd@0: ferencd@0: Note about special comment blocks: Doxygen is used to generate documentation ferencd@0: from annotated C++ sources, so be sure to use available markings to annotate ferencd@0: the purpose of the functions/classes and the meaning of the parameters. ferencd@0: ferencd@0: ferencd@0: 5. Miscellaneous ferencd@0: ================ ferencd@0: ferencd@0: * No code should be put in header files, only declarations (except for ferencd@0: templates and inline functions). ferencd@0: ferencd@0: * Try to avoid public member variables. Write accessors instead (get/set). ferencd@0: ferencd@0: * Do NOT use 'using namespace' (and especially not in header files). All ferencd@0: namespaces should be explicitely named. ferencd@0: ferencd@0: * Use the 'get' and 'set' prefix for accessors: ferencd@0: ferencd@0: Variable: m_foo ferencd@0: Get method: getFoo() ferencd@0: Set method: setFoo() ferencd@0: ferencd@0: * No more than one class per file (except for inner classes). ferencd@0: ferencd@0: * Put the inclusion for the class's header file as the first inclusion in ferencd@0: the implementation file. ferencd@0: ferencd@0: * Put the copyright header at the top of each file. ferencd@0: ferencd@0: * Write "unique inclusion #ifdef's" for header files: ferencd@0: ferencd@0: #ifndef N1_N2_FILENAME_HPP_INCLUDED ferencd@0: #define N1_N2_FILENAME_HPP_INCLUDED ferencd@0: ferencd@0: // ... ferencd@0: ferencd@0: #endif // N1_N2_FILENAME_HPP_INCLUDED ferencd@0: ferencd@0: where N1 is the top-level namespace, N2 the sub-namespace, and so on. ferencd@0: For example, class "vmime::utility::stringUtils" uses the following ferencd@0: #ifdef name: VMIME_UTILITY_STRINGUTILS_HPP_INCLUDED. ferencd@0: