Programming Rules
-----------------
duplication is #1 rookie mistake, modularity is key
avoid setters, favor immutible value types
define operations instead of setters. e.g: favor rect.resize(w, h) over setWidth and setHeight.
class interfaces should be minimal and complete
use free functions for additional functionality. e.g. `unsigned area(rect)` is better than `rect.area()`
minimal scope
avoid C arrays
if you must use a C array, put it in a struct so that you can use value initialization and normal copy semantics.
always prefer natural semantics. e.g. a == b is better than `memcmp(&a, &b, sizeof(a))`
favor unsigned integers.
constructor fully initializes an object (avoid configuration with setters)
favor exceptions over assertions or error codes
the thrower of an exception should not worry about the catching of it.
define catch blocks from the top down (nested safety nets)
favor declarative programming
favor lazy evaluation
less code means less bugs
primarily aim for a minimal and correct solution
use test-driven design.
use tracer bullets.
compile at a high warning level, treat warnings as errors
avoid deep scope nesting
avoid else branches
(?) production code might require a more explicit naming style
(?) production code might benefit from a more conserative design (less nifty)
duplication reveals bad design
the law-of-demeter is not overkill
most application-level classes should use pimpl
law-of-demeter goes hand in hand with pimpl
a little duplication is ok
design != categorization
use a top-level namespace
you may define second-level namespaces to mark boundaries betweeen broad areas like ui, networking, rpc, …
however, resist the temptation to create more sub-categories. there is no added value and it's cumbersome to maintain.
categorization is the #2 rookie mistake
top down hierarchical thinking is the root problem, not inheritance
bottom up multiple-inheritance is a technique for composition
you need to identify common and the specific parts. recognize what is orthogonal.
dynamic polymorphism is not inferior to static polymorphism
macros are not evil if you use them responsibly
function overloading is elegant way to implement static polymorphism
use template argument deduction if possible
(?) favor overloading with identity<T> over specializing a function for T
template specialization should usually be avoided for classes that are part of the public API
template specialization is most commonly used on traits, policies and small helper classes
pass argument by reference, store as pointer
passing a pointer argument tells the user that the pointer may be null and must be checked before dereferencing.
good design is a compromise between (in order of importance)
(1) inherent code quality (modularity, orthogonality, etc…)
(2) human readability
(3) tool readability