State & Change
Why history complicates everything
What this chapter is
This chapter is not about variables. It is not about mutability keywords. It is not about functional versus object-oriented debates.
This chapter is about memory.
State is memory inside a system. And memory always changes how reasoning works.
The core truth
State means the past is still present.
When state exists:
- behavior depends on history
- order matters
- repetition is no longer safe
Two identical inputs can produce different outputs because something happened before.
🧠 Mental Model State introduces time into logic.
Why state is unavoidable
Every real system has state.
- user sessions
- stored data
- configuration
- caches
- counters
- flags
Trying to eliminate state entirely is fantasy.
The goal is not to remove state. The goal is to contain it.
The real danger is not mutability
Most discussions focus on:
"Is this mutable or immutable?"
That question is secondary.
The primary question is:
Who owns this state?
Unowned state is dangerous state.
Ownership defines safety
When state has clear ownership:
- changes are intentional
- responsibilities are visible
- bugs localize
When state has unclear ownership:
- multiple actors modify it
- invariants erode
- fixes collide
🧠 Architect's Note State should have one owner, even if many can read it.
Hidden state is the worst kind
Hidden state includes:
- global variables
- shared singletons
- implicit environment dependencies
- static caches
- values modified outside visible flow
Hidden state creates action at a distance.
You change something here. Something breaks there.
⚠️ Common Drift When bugs feel "impossible," hidden state is usually involved.
Temporal coupling
State creates temporal coupling:
- this must happen before that
- this must not happen twice
- this must happen only once
Temporal coupling is fragile because:
- time is hard to see
- time is hard to test
- time is hard to control
🧠 Mental Model If order matters, order must be enforced — not assumed.
Reentrancy reveals state problems
A powerful test of state clarity is this question:
"What happens if this runs twice?"
Or:
"What happens if this runs again before it finishes?"
If the answer is unclear, state is leaking.
State vs data
Not all data is state.
- Data describes reality.
- State describes change over time.
Confusing the two causes:
- over-mutability
- defensive copying
- unnecessary resets
🧠 Perspective Stable data should stay stable. Only true state should change.
Local state vs shared state
Local state:
- easier to reason about
- easier to reset
- easier to test
Shared state:
- harder to reason about
- harder to control
- harder to debug
Shared state is sometimes necessary. It should always be explicit.
State and failure
Failures interacting with state are dangerous.
Questions every stateful operation must answer:
- what happens if this fails halfway?
- what is left changed?
- can it be retried safely?
Ignoring these questions creates:
- partial updates
- corruption
- irreversible damage
🧠 Architect's Note State changes must be atomic or recoverable.
State accumulation and drift
Over time, systems accumulate state:
- flags added "temporarily"
- caches layered on caches
- compatibility hacks preserved forever
Each addition feels small. Together, they create inertia.
⚠️ Common Drift Most legacy systems are not complex — they are over-remembering.
Minimal practice (still no code)
Problem: "A function updates a counter, saves a record, and sends a notification."
Ask:
- What state changes?
- Who owns each change?
- What happens if notification fails?
- Can this be retried safely?
If these answers are vague, the design is incomplete.
What beginners gain here
- Understanding why bugs appear "random"
- Awareness of hidden dependencies
- Respect for order and ownership
What experienced developers recognize
- Why some systems resist refactoring
- Why concurrency introduces chaos
- Why fixes create new problems
State was unmanaged.
What this chapter deliberately avoids
- Language-level mutability debates
- Framework state management patterns
- Reactive buzzwords
- Implementation details
Those come after clarity.
Closing
State is not evil. But it is expensive.
It costs:
- reasoning
- predictability
- safety
Well-contained state makes systems reliable. Leaking state makes systems hostile.
Design state as if time were your enemy — because eventually, it is.