Overview

3 The complex art of simplicity

This chapter presents simplicity as a core quality of beautiful code, but emphasizes that simplicity is not effortless. Code naturally drifts toward disorder as projects evolve, deadlines pressure teams into shortcuts, technologies age, requirements change, and developers add workarounds or overengineered solutions. Complexity is anything that makes code harder to understand, modify, or maintain, and it can appear both in small structures such as nested conditions and in larger architectural problems such as unclear boundaries or tight coupling.

The chapter explains that complexity can be measured, but only imperfectly. Cyclomatic complexity counts execution paths, while cognitive complexity focuses more directly on the mental effort required to read code, especially when flow is interrupted by nesting, branching, mixed logical operators, exception handling, or recursion. These metrics help identify hotspots, but they cannot capture everything: poor naming, confusing organization, excessive indirection, and the frustration developers feel when working with brittle code also reveal complexity. Human judgment remains essential.

To move toward simplicity, the chapter proposes practical ways to prevent complexity, organize code structure, reduce cognitive load, hide unnecessary detail behind useful abstractions, investigate suspicious legacy code, and endure unavoidable domain complexity when it cannot be removed. It stresses that refactoring often happens in multiple passes and that lower complexity scores do not automatically mean better code. Simplicity requires balance: abstractions should clarify rather than obscure, messy unavoidable logic should be isolated and documented, and teams should use reviews, communication, documentation, and thoughtful design decisions to keep code maintainable over time.

Example of a cognitive complexity code smell reported by SonarQube.
Each flow-breaking structure (for, if, else…) and each level of nesting increases cognitive complexity. In this example, the developer must keep track of several different execution paths to understand the overall logic.
The six levers of code simplicity.
Class diagrams for report generators, using the Strategy Pattern to separate the report generation logic from the orchestration code.

Summary

  • Code complexity accumulates slowly, making it difficult to spot until it becomes overwhelming.
  • Essential complexity comes from the inherent difficulty of the problem being solved and cannot be removed, only managed. Accidental complexity is introduced by poor design choices, outdated code, or overengineering and should be eliminated through refactoring whenever possible.
  • Cyclomatic complexity quantifies the number of linearly independent paths through a method by counting decision points. While still useful, it focuses on structural flow and doesn’t fully capture how difficult code is to understand.
  • Cognitive complexity is a useful metric for identifying flow-breaking structures and nested logic that affect readability.
  • SonarQube is a static analysis tool that can measure cognitive complexity, code smells, and other maintainability issues in codebases.
  • You can apply six key levers to move toward simplicity: Prevent, Organize, Reduce, Hide, Investigate, and Endure.
  • Prevent: Establish disciplined team practices—code reviews, shared conventions, meaningful commits, early design validation, and clear communication—to keep the codebase aligned and maintainable over time.
  • Organize: When growth blurs boundaries or makes navigation difficult, reorganize deliberately and in coordination with the team.
  • Investigate: Question overly complex or unclear code and weigh risks before deciding to refactor or leave code as-is.
  • Reduce: Lower cognitive complexity.
  • Hide: Separate what the system does from how it does it, exposing only what needs to be known. Applied carefully, abstraction reduces cognitive load; overused, it can obscure logic and make debugging harder.
  • Endure: Not all complexity can be removed; some is inherent to the domain and must be managed rather than eliminated. Isolate unavoidable complexity, contain it behind clear boundaries, and document it.
  • Striving for simplicity is an ongoing process. Use metrics and trust your frustration as signals to spot problematic code, then apply the appropriate levers to address it.

FAQ

What does the KISS principle mean in the context of code simplicity?

KISS means “Keep It Simple, Stupid,” though softer versions include “Keep It Short and Simple” or “Keep It Sweet and Simple.” In code, the principle means that systems should be simple enough for non-experts to understand, which improves long-term maintainability. The challenge is that achieving simplicity often requires deliberate effort and careful design decisions.

How does complexity creep into a codebase?

Complexity builds gradually through deadline pressure, shortcuts, poor design decisions, deep nesting, long methods, excessive abstraction, unclear package structures, inconsistent team practices, outdated technologies, and overengineering. Even untouched code can decay as technologies evolve, documentation is lost, developers leave, and dependencies become obsolete or unsupported.

What is technical debt?

Technical debt is the cost of shortcuts taken in code. Sometimes it is a strategic decision made to meet a deadline, but like financial debt, it accumulates interest over time. The longer it remains unresolved, the harder, slower, riskier, and more expensive future changes become.

What is the difference between complicated and complex code?

Complicated code is hard to understand from a reader’s perspective, often because it requires specific knowledge or effort. Complex code has many interconnected parts, execution paths, or relationships. Complication is subjective and depends on the developer’s experience, while complexity can often be measured through factors such as nesting, branches, and Boolean conditions.

How is cyclomatic complexity different from cognitive complexity?

Cyclomatic complexity measures how hard code is to test by counting independent execution paths, such as branches created by if, while, or switch statements. Cognitive complexity measures how hard code is to understand by focusing on mental effort, especially flow-breaking structures, nesting, and mixed logical operators. Two methods can have the same cyclomatic complexity but feel very different to read.

What kinds of structures increase cognitive complexity?

Cognitive complexity increases when code interrupts the natural reading flow. Examples include loops, conditionals, catch blocks, switch statements, ternary expressions, recursion, labeled jumps, mixed logical operators, and especially nested structures. Each new nesting level adds extra mental burden because the reader must track multiple execution paths at once.

What are the six levers of code simplicity?

The six levers are Prevent, Organize, Reduce, Hide, Investigate, and Endure. Prevent focuses on team habits that stop complexity from appearing. Organize improves project structure. Reduce lowers code-level cognitive complexity. Hide uses abstraction to shield readers from unnecessary details. Investigate helps understand legacy complexity. Endure handles complexity that cannot be fully removed.

How can teams prevent complexity before it appears?

Teams can prevent complexity through code reviews, meaningful commit messages, documentation, early design validation, and clear communication. Code reviews act as a first line of defense by catching design issues and readability problems. Good commits preserve reasoning. Documentation reduces reverse engineering. Early design discussions prevent structural mistakes, and communication keeps technical decisions consistent across the team.

What are common ways to reduce cognitive complexity?

Common strategies include limiting nesting depth, using early return statements, extracting complex Boolean expressions into well-named methods, simplifying conditions, combining conditionals with the same outcome, replacing long if/else chains with structured branching such as switch, avoiding labeled jumps, and using declarative iteration when it makes the control flow clearer.

When should complexity be hidden, investigated, or endured?

Complexity should be hidden when abstraction separates what code does from how it does it without creating unnecessary layers. It should be investigated when existing or legacy code seems overly complicated and no clear reason justifies it. It must be endured when the complexity is essential to the domain, such as tax rules or healthcare billing. In those cases, isolate the messy logic, document it clearly, and keep the rest of the code clean.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Art of Code ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Art of Code ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Art of Code ebook for free