Skip to main content

Fitness Function Design

Kata: Design a fitness function for an architectural rule. Pick a rule from your team's actual codebase - written in an ADR or implicit - and implement a check that runs automatically and gates merges.

Retrieval Prompts

  1. What is the difference between a unit test and a fitness function?
  2. Name three shapes a fitness function can take.
  3. What are the three states for an architectural claim with respect to automation?
  4. Why is an exemption path required for a fitness function to be usable?
  5. What does "fitness functions make reviews unnecessary" get wrong?

Compare and Distinguish

  • Static checks vs runtime metric thresholds. When is each appropriate?
  • Fail-fast (PR CI) vs observe-and-report (nightly). What risks does each mitigate, and what does each miss?
  • Enforcing vs documenting a rule. Why does an enforced rule decay slower?
  • Claim vs check. Why is the translation lossy, and what does that mean for unmonitored dimensions?

Common Mistake Check

Diagnose the problem in each:

  1. A fitness function is added to CI but runs only on a subset of the repo (the author's service). (partial coverage becomes proof of absence)
  2. A rule is recorded as "ADR-0052 says no synchronous billing calls" but no fitness function exists. (documented but not enforced - will rot)
  3. Exemptions are allowed without expiration. (permanent loophole - rule is effectively off for any module with one exemption)
  4. A fitness function reports percentages instead of pass/fail, blocking no PRs. (metric without a threshold is not a gate)
  5. A fitness function duplicates a unit test and adds no architectural value. (misclassified; no one will maintain it)

Mini Application

Design and ship one fitness function:

  1. Pick a claim. Choose an architectural rule your team cares about. Write it in one sentence.
  2. State its current enforcement. Doc-only, code-review-only, or automated? Why?
  3. Pick a shape. Static analysis (ArchUnit, dependency-cruiser, eslint rule), metric threshold (SLI + budget), contract test, or structural test.
  4. Implement. Write the rule in ~1-3 hours. Target a single repo.
  5. Gate CI. PR blocks on failure.
  6. Exemption path. Annotations or waivers must have an expiration; exemptions are listed on a dashboard or README.
  7. Document. In the ADR (or in a new one if the claim was undocumented), link the fitness function and state where it runs.

Candidate Fitness Functions (Pick or Adapt)

  • No direct imports across service boundaries (ArchUnit / dependency-cruiser)
  • No cyclic dependencies between modules
  • Maximum cyclomatic complexity per function
  • All outbound HTTP calls use the configured client (no raw fetch / http.Get)
  • Secrets not committed (gitleaks / trufflehog in CI)
  • p99 latency under budget for a named endpoint (synthetic probe + alert)
  • API schema matches consumer expectations (contract test with consumer snapshots)
  • No cross-team DB queries (lint on connection string references)

Critique and Rewrite

Take a fitness function you find in a public repo or a sample project. Critique:

  • what claim does it enforce, and is that claim explicitly documented in an ADR?
  • where does it run, and what drift would it miss?
  • what is the exemption policy, and is it expirable?
  • is it a true architectural check, or is it a unit test in disguise?

Evidence Check

This page is complete only when you can:

  • translate one architectural claim into an automated check in under 3 hours
  • defend the automation shape (static, metric, contract) with one paragraph
  • design an exemption path that does not permanently disable the rule
  • link the fitness function to the ADR whose claim it enforces
  • identify at least one architectural claim you cannot yet automate, with a reason