Working Fundamentals
chapter 5 of 13

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.