使い方
- インストールコマンドをコピーし、自分の環境へ導入する前にソースを確認します。
- 必要なツール、認証情報、対応環境を原文で確認します。
- 入力と成果物を指定し、出力を資料と照合します。
npx skills add https://github.com/yonatankarp/software-design-skills --skill arch-fitness-functions開始前の確認
- 導入にはモデル契約、API枠、ファイルへのアクセス許可は含まれません。
- スター数や導入数は活動の指標であり、独立した品質・安全性試験ではありません。
見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。
One-line summary
Encode architectural intent as automated checks that run on every change. If the architecture says "the domain layer doesn't depend on Spring", a fitness function fails the build when it does.
When to use this skill
- An architecture decision matters and needs to stay true over time (dependency direction, layer boundaries, no cyclic dependencies, performance budgets).
- Teams are large enough that informal "we agreed not to do X" doesn't hold across all PRs.
- Migration projects (
arch-strangler-fig) where you want to enforce that new code lives in the new shape and not the legacy. - Any architectural decision where you'd otherwise rely on code review to catch drift.
When NOT to use this skill
- Tiny project, single developer, no scaling problem.
- The architectural property is genuinely subjective and not automatable (taste, aesthetics, naming style on edge cases).
- Over-policing — every architectural rule has a cost; only enforce what you would block a PR over.
Core content
A fitness function is a test that asserts an architectural property. Like unit tests, they:
- Run automatically in CI on every change.
- Fail the build if violated.
- Document the architectural intent in executable form.
Categories of fitness function (Ford, Parsons, Kua, Building Evolutionary Architectures):
- Atomic vs holistic. Atomic checks a single property (no cycles in this module). Holistic combines multiple properties (performance + correctness under load).
- Triggered vs continual. Triggered runs on each build (most useful). Continual runs in production (latency budgets, error rates).
- Static vs dynamic. Static analyses code (dependency direction). Dynamic runs the system (response-time check).
Common static fitness functions (these are the most accessible to start with):
- Dependency direction. "Module X must not depend on module Y." Enforced via build graph or a dedicated library (ArchUnit for JVM, ts-arch for TypeScript, dependency-cruiser for JS).
- No cyclic dependencies. Detects accidental cycles introduced by a misplaced import.
- Naming conventions. "Every class in
controller/must end inController." Mostly cosmetic but cheap to enforce. - Public API stability. "No new public methods on this interface without a corresponding test." Custom check.
- Layer boundary violations. "Code in
domain/must not import frominfrastructure/." The classic hexagonal check.
Dynamic fitness functions for production architecture:
- p99 latency under a threshold.
- Memory usage bounded.
- Specific business invariants holding (no negative balances; no duplicate orders).
Example with ArchUnit (JVM, the most mature ecosystem):
@ArchTest
val domainHasNoSpringDependencies =
noClasses().that().resideInAPackage("..domain..")
.should().dependOnClassesThat().resideInAPackage("org.springframework..")Decision heuristics
- Start with one or two fitness functions enforcing the architecture's most important property (typically dependency direction). Add as drift surfaces.
- Make fitness function failures fail the build — a warning that's been ignored for a year is not a fitness function.
- Treat fitness functions like tests: each has a clear failure message that explains why the rule exists, not just what it checks.
- Don't write a fitness function for a rule you wouldn't block a PR over.
- For migration projects, fitness functions can encode "new code goes in path X, not legacy path Y" — invaluable for keeping the migration honest.
Anti-patterns
- Fitness function that nobody owns. Breaks → someone disables it → bypassed forever.
- Over-policing. Hundreds of fitness functions enforcing every preference. CI gets slow; developers learn to ignore failures.
- Style as architecture. "All method names must be camelCase" is a linter rule, not a fitness function. Don't dilute the term.
- Documentation without automation. Wiki page describing the architecture; no automated check; new joiners violate it within weeks.
- One-time check. Architecture audit done once, results filed away. Drift accumulates immediately after.
See also
arch-layered— layer boundaries are the canonical fitness-function use case.arch-hexagonal— dependency-direction-toward-domain is the canonical hexagonal fitness function.arch-adr— fitness functions encode the what; ADRs explain the why. Both belong together.
References
- Neal Ford, Rebecca Parsons, Patrick Kua, Building Evolutionary Architectures (O'Reilly, 2nd ed) — the foundational reference.
- ArchUnit documentation (JVM).
- Richards & Ford, Fundamentals of Software Architecture, governance / fitness chapters.



