Coding Guidelines
Latest revision: June 11, 2008
Preamble
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
All Code in the project MUST follow these guidelines.
Encoding
- International characters MUST NOT be used.
- You MUST ensure that line endings are consistent (either CRLF, or LF).
- You MUST add a blank line after the last line of the file.
- You MUST use ISO-8859-1 encoding for the source code, for MS-Windows compatibility.
Header
All project source code (.cpp, .h, .hpp files) MUST include a header stating the author, license, description and any other optional comments, using the following template:
/********************************************************************************** * Name: filename.extension * Purpose: Define the filename purpose (i.e. "defines class XYZ", w/o quotes) * Author: Author name (obfuscated e-mail goes here) * Created: YYYY-MM-DD * Copyright: Author name (obfuscated e-mail goes here) * License: License (example: GPL version 3 or later) * Comments: (Comment lines ARE OPTIONAL) * (Comment lines ARE OPTIONAL) **********************************************************************************/
- Comments are a very important part of the code. When in doubt, comment.
- All data in the header MUST start at the same column.
- The top and bottom lines of the header (the ones with the series of asterisks) MUST cover the length of the text, but they MUST NOT be more than 70 characters wide. For this reason, wrapping at less than 50 columns is RECOMMENDED.
- Comment lines are OPTIONAL, but if included, they MUST start at the same column as the other data.
Comments
- Swearing and offending words inside (or outside) the comments are FORBIDDEN. However, ambiguous acronyms MAY appear in extreme cases. Use with care.
- Comments made with the purpose of documentation MUST use doxygen syntax. See the doxygen code documentation webpage.
- ALL class methods MUST include parameters and return doxygen commands.
- Methods that require a long description MUST include the @brief command for a brief description.
- ALL header declarations MUST be documented!
- Internal private class methods MUST be documented in the implementation, before the function starts.
- Same goes with functions not declared in header files.
- When dealing with difficult-to-understand logic, you SHOULD include clearly detailed use cases in the comments.
- Actually, try to include use cases for all internal functions.
- All comments MUST be in english. Try to keep a good spelling and grammar.
- Try to make the documenting comments start on the same column. Otherwise they look ugly.
The Code
Naming conventions
- Class member variables MUST carry the "m_" prefix, except if the class is data-only.
For pointers, including a "p" in the prefix, after the underscore is NOT RECOMMENDED. - Static variables MUST carry the "s_" prefix.
- Class names and functions (but not variables) MUST use uppercase for the first letters of each distinctive word, and lowercase for the rest of the class/method name. Underscores MAY NOT be used.
- Class Member variables MUST be all lowercase, except the first character after the prefix. This first character SHOULD be lowercase.
- Function parameters SHOULD be all lowercase.
- For local variables, using all lowercase is OPTIONAL.
- Local variables MAY use the PHP naming convention. Like "str_notfound" for predetermined string constants.
Indentation, spacing and brackets
Opening brackets MUST be in the same line as the preceding declaration / conditional statement. Example:
class MyNiftyClass { public: MyNiftyClass(); MyNiftyMethod() { if(somevarialbe) { DoSomething(); } else { DoSomethingElse(); } } };
- Indentation MUST be done with spaces, not tabs. It MUST be of 4 characters wide.
- Between the class declaration and the public / private / protected statements, there MUST be indentation.
- Between the public/private/protected statements and the inside declarations, there MUST be indentation.
- Between function implementations and/or other declarations inside .cpp files, there MUST be at least one empty line.
- if / else cases SHOULD always include the opening { and closing } brackets, even if they're one statement long.
Exceptions are when the statement is included in the same line. But it's NOT RECOMMENDED.
Code clarity
- Code SHOULD NOT use the ? : operators heavily.
- Code MUST NOT, I repeat, MUST NOT use long combinations of ? : and/or function return values (i.e. a = (ptr* mypointer = somefunction() ? a : b) ? c : d).
Programming Patterns
- In all your code, try to use the MVC, multitier, and/or Visitor Design pattern whenever possible. If so, you MUST document which tier goes where.
- For documenting tiers and wrappers, you MUST EXPLICITLY COMMENT: "ALL calls to x/y class must be done through z class."
- Wrapper functions SHOULD be as generic as possible.
- Classes / data structures declared in a tier MUST NOT be used by tiers not directly connected to that tier.
- If you must use a shared data structure, it SHOULD be as generic as possible and depend on the least number of files.
- When dealing with multi-tiered code, a class diagram (UML if possible) MUST be created and shared with other developers to add to the documentation.
- Functions MUST have only one return point, unless you're checking for parameter validity and return before the function logic starts. You MUST use the "do { ... break; } while(false);" pattern in these cases.
- Singletons (single-instance classes) are encouraged, but must not be abused.
- Gotos are forbidden. If you must use goto-like structures, try to use the "do { } while(false);" pattern.
- For string operations, Hardwired string lengths MUST NOT be used AT ALL. Instead, you MUST calculate the string's length and use the result for the required operations.
- Actually, hardwired ANYTHING is forbidden. If you must use constants, calculate them at runtime using a one-time initalization routine.
Try to declare all the text and constants at the beginning of your functions, and keep the logic later. Example:
function myfunc() { const wxString err_notfound = _("Not found!!"); const wxString msg_ok = _("OK!"); const int somelimit = 25; if(somefunction() > somelimit) { wxMessageBox(err_notfound); } }
This way the code is much clearer and changes in the strings are guaranteed not to affect the code logic.
- Try to keep similar functions grouped in class declarations and implementations.
Compiler warnings
- Compiler warnings MUST be kept to a minimum.
- You SHALL NOT leave these for later.
wxWidgets vs. STL containers
- wxStrings MUST be used instead of std::string.
- wxArrays SHOULD NOT be used. Whenever possible, use STL containers versus wxWidgets containers.
- Exception is when you need to use wxWidgets functions that require wxArrays.
- When in doubt, read the manual.
Custom wxWidgets classes
- Custom wxWidgets classes and containers SHOULD start with the "wx" prefix.
- Custom wxWidgets classes MUST be 100% independent of non-wxWidgets-specific code.
- Custom wxWidgets classes should go in the "wxcustomclasses" directory.
- If possible, try to keep the custom wxWidgets classes headers and implementations in the same directory.
Macros (#defines) and C++ templates
#defines MUST NOT be used, with the following exceptions:
- If you import a generic class that uses strings and you want to make them compatible with wxWidgets. But in that case, you MUST NOT use the generic name "string", instead use another specific name (like myclassstring or something).
- For wrapping an entire header to prevent double inclusion
- If you cannot comply with the above requirement, you MUST group #ifdefs inside a WRAPPER FUNCTION.
- Use of C++ templates is RECOMMENDED, but complex templates SHOULD NOT be used unless it's necessary and very beneficial to code simplification.
Dialogs, XRC and FPB resources
- Whenever possible, you SHOULD use a GUI such as wxFormBuilder or wxSmith for the dialogs. (wxFormbuilder is RECOMMENDED).
- Whenever possible, resources SHOULD be exported as XRC.
- The original .fbp resouces MUST be included in the same directory so we can edit them later.
- Widgets SHOULD use the "idSomething" naming convention for use with the wxXmlResource class.
Code licensing
Licensing guidelines are NOT OPTIONAL. Unlike other guidelines stated in this page, disobeying the Code licensing guidelines SHALL result in you being expelled from the team.
- For the license of the files you created, if you want your code to be used in a wider variety of projects, you MAY use a license broader than GPLv3 (like including a linking exception). But the license MUST be GPLv3 compatible.
- If you choose to use the GPLv3 license, you MUST provice forward compatibility in the license, stating in the header (see above in the header section) that the code is released as "GPL version 3 or later". If you disagree with this particular statement, you MUST contact the project leader to get to a mutual agreement.
Final notes
All the above guidelines are written for the benefit of the public. If you feel that some code cannot comply with some of the above guidelines, please discuss it with the other developers so we can reach a concensus.