
Complicated, Complex, and Everything in Between
Looking back through my archive, I found myself rereading a piece I wrote on Nudging and Boosting Complex Systems. What struck me is how often we blur the line between complicated and complex when we talk about software.
A car engine is complicated, not simple, but ultimately knowable. With enough expertise, you can take it apart, understand each piece, and put it back together. Much of software at the module level is the same. A function or service might be difficult to follow, but it can be understood, tested, and predicted.
But software systems, especially modern ones, sit in the complex space. They are built from layers of dependencies, abstractions we often don’t see, and the work of multiple teams. As the XKCD dependency comic reminds us, everything often rests on some small, unseen library maintained by one person in their spare time. In these kinds of systems, no single person can hold the full picture. Too many moving parts, too many interactions, too many possibilities.
This distinction between complicated and complex matters, because it shapes how we think about risk and quality. Complicated problems can usually be solved with enough expertise or documentation. Complex systems, by contrast, are never fully knowable. Their behaviour emerges only when the parts come together, and sometimes only when they are in motion.
That’s why I keep returning to the idea that quality is emergent. You can’t look at the individual parts of a system and add them up to equal quality. It’s the interactions between code, tools, and people that shape the overall outcome. And often, it’s those interactions that surprise us.
Complexity isn’t only technical. It’s also human. As we add more teams, the lines of communication multiply, and so do the chances of misunderstanding. Dependencies shift from the purely technical into the social: who knows what, who maintains what, and who we trust to notice when something has changed.
The good news is that we are not powerless. By recognising where things are complicated and where they are complex, we can nudge our teams towards clearer language and boost their ability to handle the uncertainty that comes with complexity. Sometimes that’s as simple as asking, “Is this complicated, or is it complex?” before deciding what level of testing, review, or exploration is needed.
For me, this distinction has changed how I look at almost every release decision. If something is complicated, tests and expertise can give us confidence. If something is complex, then we might need to look wider: exploratory testing, broader monitoring, or simply better conversations across teams.
You can read the full post below:
And if this way of thinking resonates, there are plenty more essays in my archive exploring uncertainty, testing, and the culture of quality.