“Software design is a constant battle with complexity.” — Eric Evans
We all intuitively understand complexity—you know it when you see it. However, to win the battle, it’s crucial to define complexity clearly and understand its causes. The most useful definition, in my view, comes from the Cynefin framework.
Cynefin
Cynefin is a decision support framework that guides decision-making in different types of situations—domains. One of these domains is complexity, providing a succinct way to define what complexity is.
Suppose you want to make a change in a software system and know exactly what the outcome will be. That’s not complexity; it’s a simple system.
If you don’t know the outcome but can consult an expert who does, that’s not complexity either; in Cynefin terms, you’re dealing with a complicated system.
However, if the only way to determine the outcome is to make the change and observe what happens, you are dealing with a complex system.
In other words, if the relationship between cause and effect can only be identified in hindsight, that’s complexity. You might argue that a cause-effect relationship may be “complex” for one person but trivial for another, and you’d be right.
Complexity is Subjective
A system’s design directly affects its complexity, but another key factor is our cognitive abilities and their limits.
complexity = 𝑓(system design, cogntive limits)
Studies have estimated our cognitive limits. In the 1950s, research suggested that, on average, we can hold 7 ± 2 units of information in mind simultaneously. When the experiment was repeated 50 years later, the results dropped to 4 ± 1 units. If this trend continues, complexity will only increase over time.
How do we battle system complexity? The primary tool is modularity.