Fitness functions for development

Pulling tangled earbuds from your pocket often results in a mess that tightens when pulled hard.
However, if you hold the knot loosely and apply a series of gentle, rhythmic nudges, the slack allows gravity and physics to find the path of least resistance.
The chaos organizes itself back into a straight line.

“Always Tangled When the Skype Rings” by Quinn Dombrowski, via Wikimedia Commons (CC BY 2.0). Hover to play the genetic-algorithm animation.

This is directed emergence: a consistent, external force driving a chaotic system toward a specific, desirable outcome.

Fitness Functions: Evolutionary Architecture vs. Clean Architecture

Building Evolutionary Architectures
Ford, Parsons, Kua
O’Reilly | Goodreads
Clean Architecture
Robert C. Martin
InformIT | Goodreads

How Building Evolutionary Architectures introduces fitness functions

Fitness functions are the book’s central original concept.
Borrowed from evolutionary computing (where a fitness function scores how well a candidate solution solves a problem), the idea is repurposed for software architecture: an objective, automated check that a desired architectural property is still being maintained.

They are the direct answer to: “How do you prevent architecture from rotting over time?”

The book categorizes fitness functions along several axes:

  • Atomic vs. holistic: one dimension vs. multiple interacting dimensions.
  • Triggered vs. continuous: CI pipeline checks vs. always-on production monitoring.
  • Static vs. dynamic: fixed thresholds vs. context-sensitive thresholds.

Concrete examples include:

  • dependency direction enforcement,
  • performance budgets in CI,
  • cyclic dependency detection,
  • and data freshness monitors in streaming systems.

How Clean Architecture relates

Clean Architecture does not explicitly introduce fitness functions.
What it does introduce are structural rules that fitness functions are ideal for enforcing:

  • The Dependency Rule: dependencies point inward toward business logic, never outward toward frameworks or I/O.
  • Stable Abstractions Principle: stable components should not depend on volatile ones.
  • Layer separation: entities, use cases, interface adapters, and frameworks stay strictly apart.

These rules are powerful principles, but they still leave one gap: how do you ensure they are not quietly broken over months and years of team change?

The relationship between the two

Fitness functions are the enforcement mechanism that Clean Architecture does not provide directly.

  • Clean Architecture defines what structure should exist.
  • Building Evolutionary Architectures explains how to continuously enforce that structure.

Encoding the Dependency Rule as an automated ArchUnit check in CI is a textbook fitness function: a design principle becomes an executable guardrail.

The LLM Coding Agent: Speed Without Soul

In software development, we are entering a period of unprecedented nudging via LLM coding agents.
These autonomous entities can refactor modules and ship code while developers sleep.
While this looks like infinite velocity, it carries a hidden risk: unvetted growth.

When code is generated faster than humans can review it, the intuitive sense of architectural integrity is lost.
Without human oversight, these agents can optimize for immediate completion over long-term health, leading to:

  • The technical debt tsunami: redundant logic and inconsistent patterns.
  • Development stagnation: the codebase becomes so dense and tangled that even the AI eventually fails to navigate it, bringing velocity to a halt.

The Fitness Function: An Automated Nudge

To prevent AI-driven repositories from becoming unmanageable, we need a digital version of that gentle outer force.
A fitness function is an automated check that provides an objective assessment of architectural integrity.

Instead of checking only whether code works, it checks whether the system stays healthy while it evolves.

By embedding these rules into CI/CD, you create architectural gravity:

  • Enforce layering: fail builds when a UI component directly touches persistence concerns.
  • Complexity caps: force oversized functions to be split into smaller, testable units.
  • Dependency rules: keep business logic isolated from frameworks and delivery mechanisms.

The Connection to Coding Agents

At 5:01, the physics explanation mirrors how software systems evolve under AI-driven change:

  1. The agent (the shaking): an LLM agent supplies raw movement and change, constantly reshaping the codebase.
  2. The fitness function (the physics/gravity): architectural constraints bias that movement toward a lower-energy state: cleaner, simpler, and more decoupled.

Without constraints, the agent’s shaking can simply tighten knots until the system reaches maximum entropy: the classic Big Ball of Mud.

See also

Conclusion

We do not need to micromanage every line produced by AI.
We need to define the fitness of the system and keep applying automated nudges so inevitable complexity moves toward clarity.

Back to home