Commonly occuring good advice aimed at improving maintainability.
- Avoid duplication, tautology, repetition, duplication, and saying the same thing over and over in different ways.
- Everything (words, statements, comments) should have a clear purpose.
- Don't repeat yourself - Wikipedia
- Occam's razor - Wikipedia
- Chesterton's fence - Wikipedia
- Avoid complexity.
- Encourage simplicity.
- Simple Made Easy - Rich Hickey (2011)
Modularity extends far beyond C++ modules or translation units, and includes the organisation, contents within and relationships between:
- Functions
- Objects
- Source files
- Packages
- Documents
- Standards and Conventions
- Projects
- Teams
Many well-meaning projects store toolchain configuration in their build system description. Here's an example of a C++ project combining the concerns of configuring a specific compiler, with describing build targets. This is very common because CMake makes it easy to do. In reality, a CMakeLists.txt file should never contain a compiler flag because this couples the description of what targets to make (a build system concern) with what flags to pass when building (a toolchain concern). The result is a brittle configuration which breaks immediately when a novel toolchain is used.
Within any organisational unit cohesion is increased where lower-impact decisions (formatting, naming, and paradigm conventions) are applied consistently throughout.
Individual units may be constituent parts of a larger unit, e.g. multiple package dependencies in a project. The sub-units should be free to make and apply contrary decisions, otherwise coupling ensues.
- Avoid cycles in your graphs.
- Recursion
- CI pipelines which are triggered by pushes, and also cause pushes (see GitLab guidelines).
If something disappointing happens:
- fail
- don't try to muddle on
- don't try to be 'helpful' to get around the problem with the addition of complexity.
- When a
std::map::operator[]lookup failed to find an element matching the given key, it creates one instead. This leads to a cascade of additional complexity in the design, and makes the API less reasonable in the case that the looking is successful.
-
Don't Repeat Yourself / Avoid Tautology, i.e. describe the pattern; don't be the pattern
-
When tautology exists in the domain, model it, e.g.:
- if a model uses "ATM Machine", don't be afraid to write a variable,
automatic_teller_machine_machine. This isn't tautology in the nameing, merely a reflection of unavoidable tautology in the system. - if a library reuses names, e.g.
fmt::format,string::string, orranges::range, in a tutological name, don't try to avoid this tautology when you model around it. - If Sarah of Sarah's Sandwiches has a nametag, it's path might be "/Sarah's Sahdwiches/Sarah/Sarah's nametag.svg". Given the nametag files might be copied to a common location, this is either not tautological, or perferable to a DRYer filename.
- if a model uses "ATM Machine", don't be afraid to write a variable,
Most poor solutions I see appear to be the authors first attempt at a solution.
- "Design it Twice", Chapter 11 of A Philosophy Of Software Design, John Ousterhout
- Command / Query - goes under UNIX way: each thing does only one thing