Difference between revisions of "Coding Style"
m (typo fix) |
|||
(24 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
− | This article details the coding style that should be adopted when writing changes to the [[aMule]] codebase. | + | This article details the coding style that should be adopted when writing changes to the [[aMule]] codebase. Various useful information for [[aMule]] (new and old) [[aMule_devs|developers]] can also be found here. |
== Formatting == | == Formatting == | ||
Line 40: | Line 40: | ||
=== Brackets === | === Brackets === | ||
− | + | Opening brackets are placed on the same line as the construct with the exception of non-inlined functions, structs and classes. Prefer the usage of brackets, even when optional, as in the case of ''if''/''while''/etc blocks. | |
=== Misc === | === Misc === | ||
Line 49: | Line 49: | ||
== Documenting comments == | == Documenting comments == | ||
− | Always remember to documment new functions and classes! Examples of documented classes | + | Always remember to documment new functions and classes! Examples of documented classes can be found in ''CMD4Hash.h'', ''BarShader.*'', ''ServerListCtrl.*'' and others. More information on the usage and syntax of [http://www.stack.nl/~dimitri/doxygen doxygen] can be found in the [http://www.stack.nl/~dimitri/doxygen/manual.html doxygen documentation]. |
Use the following format, which is [http://www.stack.nl/~dimitri/doxygen doxygen] compatible. | Use the following format, which is [http://www.stack.nl/~dimitri/doxygen doxygen] compatible. | ||
Line 79: | Line 79: | ||
* Function names should follow the AllWordsAreUppercase convention | * Function names should follow the AllWordsAreUppercase convention | ||
− | * Function arguments should follow the conventions for local | + | * Function arguments should follow the conventions for local variables described below |
===== Variables ===== | ===== Variables ===== | ||
Line 96: | Line 96: | ||
* Use ALLUPPERCASE names | * Use ALLUPPERCASE names | ||
+ | |||
+ | * Whenever possible, prefer const variables to pre-compiler defines. We've already had problems with nameclashing caused by defines, so we might as well not increase the chances of it happening again. Actual constants also has the major advantage that we gain proper type-safety. | ||
===== Filenames ===== | ===== Filenames ===== | ||
Line 104: | Line 106: | ||
Remember to mark functions and arguments (pointers, references) as const where possible. This increases the ability for us to write safer code and is a good thing. | Remember to mark functions and arguments (pointers, references) as const where possible. This increases the ability for us to write safer code and is a good thing. | ||
− | |||
− | |||
− | |||
− | |||
===== References ===== | ===== References ===== | ||
Always use references where passing large datatypes suchs as [http://www.wxwidgets.org/manuals/2.4.2/wx368.htm ''wxString''] and ''CMD4Hash'' and only use non-const references if we are going to change the passed variables. | Always use references where passing large datatypes suchs as [http://www.wxwidgets.org/manuals/2.4.2/wx368.htm ''wxString''] and ''CMD4Hash'' and only use non-const references if we are going to change the passed variables. | ||
+ | |||
+ | === Lists/etc === | ||
+ | |||
+ | Only use raw arrays when absolutely necessary, in ALL other cases use: | ||
+ | 1) STL containers, or | ||
+ | 2) wxWidgets containers | ||
+ | |||
+ | However, for consistency STL containers should always be used unless there is a major reason for doing otherwise. Using STL containers gives us the advantage of making it possible to use the many algorithms in the STL library and they are usually faster than the corresponding wxWidgets container. | ||
+ | |||
+ | === Deleting === | ||
+ | |||
+ | Deleting a NULL pointer is a valid operation, so checks against NULL only clutter the code needlesly. | ||
=== Hacks === | === Hacks === | ||
Line 122: | Line 132: | ||
Whenever possible, prefer [[wxWidgets]] functions to system calls, as this reduces the dependencies on specific function-calls that may or may not be available on other platforms. | Whenever possible, prefer [[wxWidgets]] functions to system calls, as this reduces the dependencies on specific function-calls that may or may not be available on other platforms. | ||
+ | |||
+ | == IMPORTANT: What to avoid (The special 'I kill you' section!) == | ||
+ | |||
+ | * Do NEVER NEVER use unicode2char and char2unicode functions at all. Same for unicode2UTF8 and UTF82unicode, and anything related to converting unicode wxStrings into char or wchar buffers. This is specially true with functions dealing with interface, where we should ALWAYS use wxStrings, and never use string conversion to construct that wxString. | ||
+ | |||
+ | :''The only places this is allowed is on printf() calls for debug. And if you REALLY need to use them in other scenario, like network communication or file handling use them VERY carefully. There are comments about the proper use at the beggining of StringFunctions.h. If you don't know if it's right or what to use, just ask, probably Kry is the best one to reply to that questions. Make someone review the code if you're not experienced and want to use that.'' | ||
+ | |||
+ | * Do NEVER use wxString::c_str() or wxString::GetData() or similar functions. If you ever need to do such thing, it must be one of the special cases above where unicode2char can be used. | ||
+ | |||
+ | :''If you, for some reason, know that the string is ANSI (like the MD4 hashes stored on wxStrings), you can use c_str() there (NEVER GetData()!) to avoid the CPU usage of the conversion functions, but you MUST put a big warning about it above the function call.'' | ||
+ | |||
+ | * Do NEVER use wxFile or wxFFile - use CFile instead. It has several bugfixes over wxFile, and it will work perfectly for handling UTF8 filenames on unicode aMule, such as anything non-ascii. | ||
+ | |||
+ | :''There should be no problem using wxFile and wxFFile for amule-related files, like server.met and others, that are never non-ansi, but the use of CFile is advisable to keep coherence over the system and easier replacement when a valid wxFile is released from wxWidgets devs.'' | ||
+ | |||
+ | * Do NEVER use wxFind{First,Next}File. Use the CDirIterator class found in CFile.*. Reasons for this are the same as for wxFile and wxFFile: they don't handle unicode filenames properly. | ||
+ | |||
+ | :''No, there's not exception for this. Just never use it.'' | ||
+ | |||
+ | * Do NEVER use wxStat or wxDirExists, use the static CFile::Stat() and CheckDirExists. Reasons are the usual ones: handling of unicode filenames. | ||
+ | |||
+ | :''No, there's not exception for this. Just never use it.'' | ||
+ | |||
+ | * Avoid wxDateTime::Now().Format{Time, Date} as if it were Satan itself. Mainly, it asserts and breaks on several locale, mainly chinese and other asian languages. Use wxDateTime::Now().FormatISO{Time, Date}. People will have to live with english formated date and time strings. | ||
+ | |||
+ | :''No excuses for this either. It will have to go like this till wx devs fix it.'' | ||
+ | |||
+ | * When you use a string to build a wxString, like "aMule", you MUST use wxT("aMule") if you want it not to be translated and _("aMule") if you want it to be translated. Failure to do so will result in aMule not being compilable in unicode mode, and the coder responsive will be killed and buried alive, not neccesarily in that order. | ||
+ | |||
+ | :''As a side note, debug messages should be ALWAYS in english, and messages meant to be for the user should be translated. This is so we can read debug info without translating it.'' | ||
+ | |||
+ | * Do NEVER use CList/CTypedPtrList. This classes were a implementation of a MFC-compatible CList, and they are hand-made lists. they're known to be buggy and had to be fixed several times in the past. Instead, use stl containers or wxWidgets containers, as said on Lists/etc section. As a matter of fact, if you see a CList or CTypedPtrList on the code, clean it. | ||
+ | |||
+ | :''I said 'NEVER' because I meant 'NEVER'. No excuses at all, or you'll be drawn and quartered, and your parts will be exposed at the four corners of the [[aMule]] world as deterrent.'' | ||
+ | |||
+ | * Do NEVER EVER use [http://en.wikipedia.org/wiki/C_trigraph ANSI C trigraphs]. If you don't know what they are, you're lucky. | ||
+ | |||
+ | :''The above applies. In addition some keelhauling might be introduced.'' | ||
+ | |||
+ | * Do NEVER use 'malloc' or 'free' unless absolutely neccesary. Use 'new' and 'delete'. | ||
+ | |||
+ | :''A example of a place where malloc can (and must) be used, is when dealing with C-libs, in all other cases it should be avoided!'' | ||
+ | |||
+ | |||
+ | Probably more things I should remember, so I'll make this list bigger later. | ||
+ | |||
+ | == Usefull information == | ||
+ | |||
+ | * [http://www.joelonsoftware.com/articles/Unicode.html Basic Introduction to Unicode]. | ||
+ | * [http://www.sgi.com/tech/stl/table_of_contents.html An excellent reference to the STL implementation that GCC also uses]. | ||
+ | * [http://www.acmqueue.com/modules.php?name=Content&pa=showpage&pid=271 How Not to Write FORTRAN in Any Language]. | ||
+ | * [http://emuleplus.info/forum/index.php?showforum=23&hyperlink=/Developers/KB/Diagrams ED2K/eMule protocol flow-diagrams]. |
Latest revision as of 10:15, 16 January 2009
This article details the coding style that should be adopted when writing changes to the aMule codebase. Various useful information for aMule (new and old) developers can also be found here.
Contents
Formatting
Indenting
Use tabs
Always use tabs for indenting, do not use spaces. The size of each tab should be equal to 4 spaces.
Scopes
Indent inside new scopes, including classes, structs, functions, etc.
Examples:
if ( false ) { ... } else { ... }
class foo { foo() { ... } }
Whitespace
Place whitespace between brackets and keywords, and between operators and variables:
if (something == true);
rather than
if(something==true);
Brackets
Opening brackets are placed on the same line as the construct with the exception of non-inlined functions, structs and classes. Prefer the usage of brackets, even when optional, as in the case of if/while/etc blocks.
Misc
- When using the trinary operator, place brackets to promote readability.
- Add a space after the // chars when writing comments.
Documenting comments
Always remember to documment new functions and classes! Examples of documented classes can be found in CMD4Hash.h, BarShader.*, ServerListCtrl.* and others. More information on the usage and syntax of doxygen can be found in the doxygen documentation.
Use the following format, which is doxygen compatible.
Functions, classes, structs, etc
/** * <Short description> * * [@param <Param_1 description>] * [@param <Param_n description>] * [@return <return value description>] * * [Long description] * [@see <reference to other relevant function>] */
Variables, typedefs, constants, etc
//! <Description>
Coding
Naming Style
Always try to use descriptive names, except when it adds nothing to the readability, such as iterator varibles and counters (it, i, x, y, etc).
Functions
- Function names should follow the AllWordsAreUppercase convention
- Function arguments should follow the conventions for local variables described below
Variables
- Names should follow the firstWordLowerCaseRestUpperCase convention
- Prefix global variables with g_
- Prefix static variables with s_
- Prefix member variables with m_
Classes
- Prefix classnames with C
- Names should follow the AllWordsAreUppercase convention
Constants
- Use ALLUPPERCASE names
- Whenever possible, prefer const variables to pre-compiler defines. We've already had problems with nameclashing caused by defines, so we might as well not increase the chances of it happening again. Actual constants also has the major advantage that we gain proper type-safety.
Filenames
- For classes, use the classname without the "C" prefix.
Const correctness
Remember to mark functions and arguments (pointers, references) as const where possible. This increases the ability for us to write safer code and is a good thing.
References
Always use references where passing large datatypes suchs as wxString and CMD4Hash and only use non-const references if we are going to change the passed variables.
Lists/etc
Only use raw arrays when absolutely necessary, in ALL other cases use:
1) STL containers, or 2) wxWidgets containers
However, for consistency STL containers should always be used unless there is a major reason for doing otherwise. Using STL containers gives us the advantage of making it possible to use the many algorithms in the STL library and they are usually faster than the corresponding wxWidgets container.
Deleting
Deleting a NULL pointer is a valid operation, so checks against NULL only clutter the code needlesly.
Hacks
Always try to avoid odd hacks and in general try to avoid abnormal stuff, assignments in if constructs and the like for instance should be avoided when possible. Also try to avoid the usage of void pointers as they result in a almost total loss of type-safety.
Helper-functions
Helper functions which can have use across the app should be placed in otherfunctions.h.
Whenever possible, prefer wxWidgets functions to system calls, as this reduces the dependencies on specific function-calls that may or may not be available on other platforms.
IMPORTANT: What to avoid (The special 'I kill you' section!)
- Do NEVER NEVER use unicode2char and char2unicode functions at all. Same for unicode2UTF8 and UTF82unicode, and anything related to converting unicode wxStrings into char or wchar buffers. This is specially true with functions dealing with interface, where we should ALWAYS use wxStrings, and never use string conversion to construct that wxString.
- The only places this is allowed is on printf() calls for debug. And if you REALLY need to use them in other scenario, like network communication or file handling use them VERY carefully. There are comments about the proper use at the beggining of StringFunctions.h. If you don't know if it's right or what to use, just ask, probably Kry is the best one to reply to that questions. Make someone review the code if you're not experienced and want to use that.
- Do NEVER use wxString::c_str() or wxString::GetData() or similar functions. If you ever need to do such thing, it must be one of the special cases above where unicode2char can be used.
- If you, for some reason, know that the string is ANSI (like the MD4 hashes stored on wxStrings), you can use c_str() there (NEVER GetData()!) to avoid the CPU usage of the conversion functions, but you MUST put a big warning about it above the function call.
- Do NEVER use wxFile or wxFFile - use CFile instead. It has several bugfixes over wxFile, and it will work perfectly for handling UTF8 filenames on unicode aMule, such as anything non-ascii.
- There should be no problem using wxFile and wxFFile for amule-related files, like server.met and others, that are never non-ansi, but the use of CFile is advisable to keep coherence over the system and easier replacement when a valid wxFile is released from wxWidgets devs.
- Do NEVER use wxFind{First,Next}File. Use the CDirIterator class found in CFile.*. Reasons for this are the same as for wxFile and wxFFile: they don't handle unicode filenames properly.
- No, there's not exception for this. Just never use it.
- Do NEVER use wxStat or wxDirExists, use the static CFile::Stat() and CheckDirExists. Reasons are the usual ones: handling of unicode filenames.
- No, there's not exception for this. Just never use it.
- Avoid wxDateTime::Now().Format{Time, Date} as if it were Satan itself. Mainly, it asserts and breaks on several locale, mainly chinese and other asian languages. Use wxDateTime::Now().FormatISO{Time, Date}. People will have to live with english formated date and time strings.
- No excuses for this either. It will have to go like this till wx devs fix it.
- When you use a string to build a wxString, like "aMule", you MUST use wxT("aMule") if you want it not to be translated and _("aMule") if you want it to be translated. Failure to do so will result in aMule not being compilable in unicode mode, and the coder responsive will be killed and buried alive, not neccesarily in that order.
- As a side note, debug messages should be ALWAYS in english, and messages meant to be for the user should be translated. This is so we can read debug info without translating it.
- Do NEVER use CList/CTypedPtrList. This classes were a implementation of a MFC-compatible CList, and they are hand-made lists. they're known to be buggy and had to be fixed several times in the past. Instead, use stl containers or wxWidgets containers, as said on Lists/etc section. As a matter of fact, if you see a CList or CTypedPtrList on the code, clean it.
- I said 'NEVER' because I meant 'NEVER'. No excuses at all, or you'll be drawn and quartered, and your parts will be exposed at the four corners of the aMule world as deterrent.
- Do NEVER EVER use ANSI C trigraphs. If you don't know what they are, you're lucky.
- The above applies. In addition some keelhauling might be introduced.
- Do NEVER use 'malloc' or 'free' unless absolutely neccesary. Use 'new' and 'delete'.
- A example of a place where malloc can (and must) be used, is when dealing with C-libs, in all other cases it should be avoided!
Probably more things I should remember, so I'll make this list bigger later.