Understandability

Each codebase must be understandable and easy to change by new developers with minimal experience of the application.

Rationale

Almost all software continues to require changes through its life, whether to fix bugs, add new features or address security vulnerabilities. Sooner or later, most software ends up being maintained by people other than those who created it. In order to be able to change the software a developer needs to be able to understand it — or at least the part of it that they need to change. Our experience is that systems typically outlast their expected lifetime, and it’s not unusual for systems consigned to “maintenance mode” to be opened up for change when almost everyone who last worked on it has left the business.

Systems that are considered too difficult, too expensive or too risky to change will either become a limiting factor on business change or eventually lead to a Big Rewrite, which can cost millions and take several years.

Instead, we should ensure that applications’ codebases, as well as the systems that result from the interactions between them, are easily maintainable and kept that way, so that they are able to change with the business requirements. Even the process of replacing or decommissioning a system will benefit greatly from its current workings being understandable.

Implications

  • Software must be created with a clear set of tests which help the reader understand the application, and can be run from the command line with a single command.
  • Appropriate levels of documentation will need to be created and updated, with a preference for detailed descriptions of functional behaviour to be enshrined in code as tests. This includes maintaining a README describing the application and documenting the command required to build, test and run it.
  • Different audiences may require different artefacts for effective maintenance, change planning and risk management. This may include: the code, the commit history, JIRA tickets, cross-functional stories, architectural descriptions, runbooks, or formal documentation.
  • Stale documentation is worse than no documentation, so investment will be required to ensure it is up to date. Maintained reference documentation and transient delivery documentation should be kept separate, so anyone can quickly understand what they can trust.
  • Knowledge sharing can be split into two parts, the “WHATs” and the “WHYs”. The WHATs should be evident from the code, and focused reference documentation, but the WHYs should be carefully documented as decisions are made. Decision records, code comments and/or appropriately named tests can all be useful in this case. Handover of the WHYs should be done to all levels, not just to developers.
  • Each codebase should have a published set of code style guidelines, preferably importable into your IDE or text editor. At a minimum: encoding, line breaks and tabbing standards should be defined, ideally using a non-IDE-specific (or widely-supported) tool such as editorconfig.
  • Developers should refactor code and tests when needed, reassured by the presence of the rapid feedback they will receive if they break something.
  • An application should be consistent in applying a programming style throughout - such as procedural, functional or object-oriented. Many languages encourage a particular style, in which case this should be adopted in order to play to its strengths.