Miniature/Policies
(→Coding style) |
(→Coding style) |
||
Line 20: | Line 20: | ||
* Braces after newlines. | * Braces after newlines. | ||
* Variable names should be visually different from types (even if you use an editor w/o syntax highlighting), there_fore they have under_scores, no caps, no lower_Camel_Case. | * Variable names should be visually different from types (even if you use an editor w/o syntax highlighting), there_fore they have under_scores, no caps, no lower_Camel_Case. | ||
- | * Member variables should be visible, | + | * Member variables should be visible, even if your editor does not highlight member variables for you. That's why we prefix them with m_*. |
* We use no_keywords, for now. We want to avoid those function-style macros. | * We use no_keywords, for now. We want to avoid those function-style macros. | ||
* Impl files have a .cc extensions, header files use .h | * Impl files have a .cc extensions, header files use .h | ||
* Use Qt containers over std containers. | * Use Qt containers over std containers. | ||
+ | |||
+ | == Advanced Coding Style == | ||
+ | |||
+ | * Signal and slot connections should be easy to read, as they are a constant source of bugs: | ||
+ | |||
+ | connect(some_signal_source, SIGNAL(theSignalWasEmitted()), | ||
+ | some_receiver, SLOT(onTheSignalWasEmitted()), | ||
+ | Qt::UniqueConnection); | ||
+ | |||
+ | ** Details: | ||
+ | *** slots should follow the signal's name, if possible (slot prefix: on*). | ||
+ | *** Indentation is one line for the source/signal, one for the receiver/slot and another one for the connection type. | ||
+ | *** SIGNAL and SLOT should start in the same column (together with the slot's name prefix it will neatly align the parameters etc.). | ||
+ | *** Use normalized signal/slot signatures (no const keyword, no &). | ||
+ | *** Use Qt::UniqueConnection for the connection type (it's *not* the default connection type), since most of the time, it is exactly what you want. A double connection between the same source/receiver and SIGNAL/SLOT is often a bug, and this can lead to weird behaviour if the same connection code is called over and over again, leading to what I call "connection leaks". With Qt::UniqueConnection, you clearly state the intent of the connection type, while also preventing those connection leaks. | ||
+ | |||
+ | * Method parameters in header files (*not* needed in impl files) should be easy to read: | ||
+ | |||
+ | class SomeClass | ||
+ | { | ||
+ | void someMethod(SomeType arg1, | ||
+ | SomeOtherType arg2, | ||
+ | ...); | ||
+ | |||
+ | ** Details: | ||
+ | *** Move each argument to a new line. This serves two goals: header files will be easier to scan (for humans), and you'll spot those ugly methods that scream "refactor me!" faster because they have more than 3 arguments. Also, because it *is* ugly, you might just go and refactor it, which will help everyone. | ||
== How to keep code testable (and hopefully, mostly bugfree) == | == How to keep code testable (and hopefully, mostly bugfree) == |
Revision as of 21:37, 10 May 2010
This is a list of things we agreed upon in the Miniature team. TODO: List the items that are *not* fully agreed upon yet!!
Contents |
License
Miniature will use the GPL 2 (or later) for source and header files. For art contribution, Miniature will use the CC-by-sa.
Coding style
We do not need project-wide consistency, but be at least consistent inside a module and/or file.
Note: the current code violates this style. We will fix it.
We mostly try to follow the offical Qt Coding Guidelines, but with some exceptions.
- We use whitespaces over tabs.
- Max. length of a source code line is 120 characters.
- We use a Miniature namespace for all our components, and all our types(classes + typedefs) start with M.
- Exception: value types (containers, flags) start with a lowercase m, for example mMoveFlags or mHalfMove. Value types are useful when you need copy construction and copy assignment. In general though, objects are *not* copyable! MPosition is the biggest violation to this rule, feel free to fix it!
- Types are in MCamelCase, unless they are mValueTypes (see above).
- Method names are in mixedCase (= lowerCamelCase).
- Braces after newlines.
- Variable names should be visually different from types (even if you use an editor w/o syntax highlighting), there_fore they have under_scores, no caps, no lower_Camel_Case.
- Member variables should be visible, even if your editor does not highlight member variables for you. That's why we prefix them with m_*.
- We use no_keywords, for now. We want to avoid those function-style macros.
- Impl files have a .cc extensions, header files use .h
- Use Qt containers over std containers.
Advanced Coding Style
- Signal and slot connections should be easy to read, as they are a constant source of bugs:
connect(some_signal_source, SIGNAL(theSignalWasEmitted()), some_receiver, SLOT(onTheSignalWasEmitted()), Qt::UniqueConnection);
- Details:
- slots should follow the signal's name, if possible (slot prefix: on*).
- Indentation is one line for the source/signal, one for the receiver/slot and another one for the connection type.
- SIGNAL and SLOT should start in the same column (together with the slot's name prefix it will neatly align the parameters etc.).
- Use normalized signal/slot signatures (no const keyword, no &).
- Use Qt::UniqueConnection for the connection type (it's *not* the default connection type), since most of the time, it is exactly what you want. A double connection between the same source/receiver and SIGNAL/SLOT is often a bug, and this can lead to weird behaviour if the same connection code is called over and over again, leading to what I call "connection leaks". With Qt::UniqueConnection, you clearly state the intent of the connection type, while also preventing those connection leaks.
- Details:
- Method parameters in header files (*not* needed in impl files) should be easy to read:
class SomeClass { void someMethod(SomeType arg1, SomeOtherType arg2, ...);
- Details:
- Move each argument to a new line. This serves two goals: header files will be easier to scan (for humans), and you'll spot those ugly methods that scream "refactor me!" faster because they have more than 3 arguments. Also, because it *is* ugly, you might just go and refactor it, which will help everyone.
- Details:
How to keep code testable (and hopefully, mostly bugfree)
We want to have testable code, therefore we also want to follow some advanced coding standards.
For that, I will try to list some really really useful advice from this document: http://www.research.att.com/~bs/JSF-AV-rules.pdf, a coding style document for C++. Bjarne Stroustrup worked on that one, yes.
- Keep methods at a reasonable length. In general: If it doesn't fit on a screen page it's probably too long. More precise: Every method longer than 200 lines of code (including comments, yes) is too long.
- Within a method, avoid a cyclomatic complexity higher than 20 (see Appendix A regarding AV Rule 3, pp. 65, "Cyclomatic complexity measures the amount of decision logic in a single software module.", and the example).
- Avoid cyclic dependencies between classes/modules (Rationale: it's mostly an indicator for layer violations).