Good quality now, bad quality later

At the time of writing, there’s a general opinion that code quality comes down to a set of features. It often presupposes an object-oriented model, which is itself an interesting point. One version of this list might look like this:

  • Cohesive
  • Modular
  • Loosely coupled
  • Encapsulation
  • Separation of concerns

I feel these are secondary attributes; they are just our current judgements on what leads to good-quality code. I prefer to think in terms of how you might appraise these attributes. Think about a codebase that follows or doesn’t follow one of the principles, then ask yourself these questions:

  • How quickly can I debug code written like this?
  • What if I was not the author of the code?
  • How likely are changes going to conflict when working as a team?
  • Does this style of code reveal errors early or hide them?

And now, remembering that the quality of code is judged finally by the environment, we realise these metrics are a kind of fetish. Some developers worship them for their magical powers. We must define good quality by the properties of that which survives. The code’s quality must relate to whether it helps us or our organisation last a long time. That will likely mean metrics for whether it can be easily verified and maintained should hold more clout than whether it passes some objective structural analysis.

As an example, there was a recent post on Twitter (recent as I write this) about a Dutch government codebase for some medical software. It included a way to print out a percentage on some character-based output device1. The code is immediately readable but unexpectedly verbose for what it does. Any experienced developer would wince at it. However, it survived through whatever processes it went through to get there. So, is it good code? Objectively, it is, as it survived its environment, even if hardly anyone would be willing to claim they wrote it. But it says more about the environment than it does about the code.

Metrics for the future

SOLID is a collection of five principles for object-oriented software design, espoused by Robert C. Martin and first published in his 2000 paper, Design Principles and Design Patterns. They provide some difficult-to-calculate metrics, but they are metrics.

The first metric, the single responsibility principle (SRP), is usually interpreted as the quantity of code duplication. Most paradigms would agree in declaring this to be a useful indicator of quality code. Duplication or repetition is a positive feature in physical construction, but we can quickly rationalise why it’s bad in code.

The fourth principle, interface segregation, can be thought of as a measure of how much more API you reveal than necessary to your clients. Many other paradigms do not need this metric as they don’t naturally suggest over-advertising capabilities.

The open-closed, Liskov-substitution, and dependency-inversion principles each help us detect object-oriented code which is harder to maintain. We can apply these metrics to object-oriented code and declare it solid or wanting. In that sense, they are the metrics for now, while object-oriented design dominates the programming world. But what will be the metrics of our future?

A strong candidate is the use of immutable state to provide protection from the issues of concurrency as they become ever more relevant to regular programmers. Another might be data unencumbered from meaning, with principles taken from data-oriented design. Full traceability through documentation and process artefacts could surface as an accepted quality metric, as it has through ASPICE2. Others might consider data-flow testing to be a good metric for quality or at least hygienic code. Developers who use Rust or Python can already write test code in their documentation, so will that become a quality gate?

Should we start including metrics for quality outside the language, such as build times and response times to exploits? Given how connected the world is, can we accept code with a guaranteed turnaround time for exploit fixes measured in weeks? Some binding agreements already specify a response time.

All the things we think of now as good metrics might be because of our presently accepted paradigms. There are things we put up with now because that’s just how it is. In the future, we will see them as mistakes. We should know better already. Is there a way to move forward with these metrics faster? To find them before others and make better, higher quality code sooner than the competition?

2

ASPICE is the Automotive Software Process Improvement Capability dEtermination guideline and includes a lot of documentation on documentation.