pa-10 — The Hitchhiker's Guide to Doing Architecture

Companion to CONCEPTS.md, with the runnable fitness- function engine in src/go/fitness/ and the ADR + design-review templates in steps/. This is the capstone: the practices that make an architect, not just a senior engineer.

bash scripts/verify.sh runs the fitness functions over a sample architecture:

=== unhealthy architecture ===
  fitness functions passed: false
    [layering]    orders (domain) -> pg (infra) violates layering
    [max-fan-out] orders has fan-out 7 > 4
    [no-cycles]   dependency cycle detected
=== healthy architecture (dependency inversion) ===
  fitness functions passed: true

Architecture, enforced by a green/red build — not by nagging in reviews.


1. Fitness functions: architecture as tests (fitness.go)

Every layered system rots: a deadline-pressured PR sneaks in a domain → infra dependency or a cycle, and the reviewer (human, tired) misses it. The fix is to make the architecture's invariants executable tests. Rules (NoCycles, Layering, MaxFanOut) each return violations; Evaluate(graph, rules) aggregates them into a Report whose Passed gates CI. TestEvaluateAggregatesAndGatesCI proves an unhealthy architecture fails; TestCleanArchitecturePasses proves a clean one (dependency-inverted: infra depends on domain, not the reverse) passes.

This is the same machinery as pa-01 (cycles, layering) and pa-02 (contract compat), packaged as a TestArchitecture you add to CI. It's the single most leveraged thing an architect can do: the design is enforced mechanically, forever, so reviews can spend their time on judgment the machine can't make. This is "evolutionary architecture" (Ford et al.) — architecture as a continuously-tested property that can change safely.

Build it into go test and the architecture can't regress without a red build. Real tools that do this: ArchUnit (JVM), import-linter (Python), go vet/depguard, dependency-cruiser (JS).


2. ADRs: capturing the why (steps/01)

A decision without a record is a decision someone will re-litigate or accidentally revert. An ADR captures context, the decision, alternatives considered (with why rejected), and consequences — short, immutable, in the repo. The template's most important section is "alternatives considered": what you rejected and why is the senior signal, and it's what stops the team re-deciding settled questions. Notice every lab's docs/analysis.md in this book is written as a mini-ADR ("tradeoffs worth flagging," "what production adds") — the habit applied throughout.


3. Design reviews & consensus (steps/02)

The design-review checklist pressure-tests a proposal before code: boundaries, contracts, data/consistency, failure modes, rollout, observability, evolution. It's deliberately the union of the whole book, and it doubles as the spine of a systems-design interview. The reviewer's job is to find the missed failure mode — and to teach; design review is mentorship at the architecture level.

The meta-skill the JD names is building consensus. The lab can't unit- test this, but the principle is firm: authority doesn't scale across teams you don't manage. Write the RFC, prototype to replace opinion with evidence, run the review so the room owns the decision, give the first teams a paved road, and let the fitness function (not your nagging) enforce it afterward. An architect is a gardener, not a king.


4. Why this is the capstone

Every prior lab built a thing; this lab builds the practice that makes those things cohere into a platform and survive 50 engineers and three years:

  • pa-01's cycle/layering analysis → a fitness function in CI.
  • pa-02's contract compat → a fitness function in CI.
  • gw-12's migrations → recorded as ADRs, executed via the rollout ladder.
  • pa-08's PR review → the consensus/change-control mechanism for the running system.
  • The whole book's analysis.md files → the ADR habit.

The architect's output isn't code; it's leverage: paved roads, automated enforcement, recorded decisions, and aligned teams that ship better, faster.


5. Hands-on

cd src/go
bash ../scripts/verify.sh
go run ./cmd/fitsim

Then write a real ADR (steps/01) and run the design-review checklist (steps/02) against something at work.


6. Exercises

  1. Add a fitness function to a real repo: enforce "no import cycles" (or "package X must not import Y") as a failing go test / ArchUnit/import-linter rule; watch it catch a real violation.
  2. Naming/ownership rules: add a Rule that flags services without an owner tag, or packages violating a naming convention.
  3. Coupling budget over time: track total edges / max fan-out per release and fail CI if coupling grows beyond a budget.
  4. Write the ADR for a Phase 6/7 design (e.g. the eventing backbone or the SLO framework) using steps/01; include the rejected alternatives.
  5. Run a mock design review of one of your own designs with steps/02; note which boxes were assumed rather than answered — those are your risks.