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 insteps/. 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.mdfiles → 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
- 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. - Naming/ownership rules: add a
Rulethat flags services without an owner tag, or packages violating a naming convention. - Coupling budget over time: track total edges / max fan-out per release and fail CI if coupling grows beyond a budget.
- 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.
- 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.