Code as a Mental Model
I’d like you to imagine a maze, made from a green hedge laid out in a very intricate pattern. It’s a big maze, and very cleverly designed. The maze designers can easily get through the maze – they know all its tricks and the right route to follow. The hedge is substantial, neatly trimmed and maintained.
That maze is our code. The original designers have a model in their heads of how it all works. They can generally fix problems or add features in a fairly short space of time, as they know exactly where to go in the code.
Over time, the first generation designers leave. They train a few of the new team before they leave, but those developers never have the same complete picture of the design, although they build up a picture of the areas that they work in. And those second generation developers also move on in time. They hand over what they knew, but it’s even less complete.
Although we can regard developers as first or second generation in terms of when they joined a team, the actual time span can be very short. First generation developers may move on in years, or even months. We’re lucky if they hang around longer!
Generally, between the second and subsequent generations of developers, a lot of knowledge is lost. Now if anyone needs to fix something, they are more likely to hack out large parts of the hedge rather than try and figure out their way through the maze. Someone even builds a ladder to get over one part of the maze, and someone else introduces a different type of hedge to repair some of the holes.
You get the picture. There is now clumsy scaffolding in places, mixed development languages and styles, and hacks that never get cleaned up. The design integrity is gone, the mental model of what’s going on is now non-existent or at best, only covers partial areas.
This situation is what we call technical debt. Technical debt is usually considered a problem with the code, but I’d like to suggest that it is foremost a problem with our model of the code. This aligns with the rather odd phenomenon where developers can be heard to say that code “rots”. It seems that if you leave code alone for any significant amount of time, it looks a lot worse when you get back to it!
Obviously, the code is just like we left it. It’s the people who have changed. We have grown in skills and wish we’d written the code better, and we have forgotten some of the intricacies of the code, so we take longer to make changes. Those are side effects of our changing mental models.
Focusing on code as a technical skill, whilst diminishing the humans that create that software, is no longer realistic. If indeed it ever was. It’s a conundrum that technical people are often poorly equipped to deal with other people – the introverts that are the mainstream of software development will readily admit to poor people skills. So much easier to focus on the code. Code is logical and doesn’t have messy emotions! Yet we are actually a people business, at least until AI takes over completely (no, I don’t think that will happen anytime soon).
Our mental models cannot be disconnected from the code we create. Our understanding and experience as humans informs everything we do. The code may be a source of truth, but it is not the full picture.
We like to say that the code is self-documenting, but that over-simplifies the problem. The code cannot explain why it was written in a particular way. Comments could, but then they must be maintained. Tests help to explain how the code should function, which is a big step forward in understanding what it does, but still doesn’t address why decisions were made.
Those decisions are often important, and hide the “gotcha’s” in the code. A “gotcha” is when you make a perfectly reasonable change to the code that doesn’t have the effect you expected at all!
The idea of code as a mental model is fairly obvious, but it’s not how the industry talks about code and developers. Developers are swapped out of teams with little concern for the enormous amount of knowledge that leaves with them, and many businesses still think that the hard technical skills of the developer is all that counts. We mostly aren’t hiring for people who can express and discuss the models that underpin the code as a primary skill. Developers who communicate well are gold!
Only a few communities, like DDD (Domain Driven Design) expressly focus on the model of the code. They also caution that the model is not the reality. Reality lies ultimately in the code, but the mental models that are preserved around how the code should function are valuable maps that help us navigate that code base.
A final thought is to look at the Agile value of “Working software over comprehensive documentation”. Software that doesn’t work is just text with pretensions. I’d prefer an expanded value of “Understood, working code over comprehensive documentation”. I posit that software supported by comprehensive mental models is more valuable than software that currently works, but no one knows why!