Complexity Reduction
Explanation
Section titled “Explanation”Some complexity cannot be avoided. Other complexity is self-inflicted. Telling the two apart is the first step in reducing it.
Two kinds of complexity
- Essential complexity comes from the problem itself: its requirements and constraints. A solution cannot be less complex than the problem it solves.
- Accidental complexity comes from choices engineers make. Engineers created it, so they can fix it.
Brooks argued that removing all accidental complexity would not give an order-of-magnitude improvement, because essential complexity dominates. So the realistic goal is to avoid adding complexity the problem does not demand.
Why it matters
A complex design is harder to understand than a simple one. Unneeded complexity also makes a system harder to change in all directions, not only the one you expected.
Ways to reduce it
- Avoid speculative features. Features added “just in case” make software harder to modify and debug. This idea is called YAGNI (“you aren’t gonna need it”). Many small YAGNI decisions add up to a large reduction in complexity.
- Question abstractions. An abstraction that makes today’s requirements harder to understand is presumed guilty.
- Divide the system with care. How well a split into modules works depends on the criteria used to divide it. See Modularity and Separation of Concerns.
- Hide design decisions. Each module hides one design decision behind a minimal interface, so a change stays inside one module. See Information Hiding.
- Keep coupling low. Modularity, complexity, KISS (“keep it simple”) and coupling are listed together as software engineering basics. See Coupling and Cohesion.
Example
Section titled “Example”A team builds an order system. The requirements call for one payment provider. A developer proposes a plug-in framework for many future providers. The team asks whether the framework makes today’s requirement harder to understand. It does, so they skip it. They put payment handling behind one small interface in one module. If a second provider is ever needed, the change stays in that module.
Trade-offs
Section titled “Trade-offs”Simplicity has limits. Essential complexity stays, so a simple-looking design that ignores real requirements fails. Skipping speculative features also means accepting that some future needs will require work later. Judge each abstraction by whether it makes the current requirements easier or harder to understand.
Checks
Section titled “Checks”- The document separates complexity that comes from the problem from complexity the team introduced.
- Speculative features or abstractions that make current requirements harder to understand are absent or justified.
- Each module hides one design decision behind a minimal interface.
- The criteria used to divide the system into modules are stated.
Related
Section titled “Related”- Modularity
- Separation of Concerns
- Information Hiding
- Coupling and Cohesion
- Big Ball of Mud
- Technical Debt
- Architecture Principle
- Design for Change
Sources
Section titled “Sources”- Is Design Dead? — martinfowler.com, accessed 2026-11-09
- Simplify! - Part 3 — ufried.com, accessed 2026-11-09
- No Silver Bullet - Wikipedia — en.wikipedia.org, accessed 2026-11-09
- Yagni — martinfowler.com, accessed 2026-11-09
- On the criteria to be used in decomposing systems into modules – the morning paper — blog.acolyer.org, accessed 2026-11-09
- Resources - arc42 — arc42.org, accessed 2026-11-09