• Terms of Service

Learn Internet Grow

Tech Skills

  • Learn
  • Books
  • Search
  • Create
  • Measure
  • Secure
  • Share
  • Terms of Service

Architecture Fitness Functions for Bounded Contexts

Filed Under: Measure Tagged With: Architecture Fitness Functions, Architecture Governance, ArchUnit, Bounded Context, Code Quality, Continuous Integration, Coupling Metrics, Dependency Management, Domain-Driven Design, Evolutionary Architecture, Software Architecture, Software Metrics

You drew the boundaries. You named the bounded contexts, wrote the ubiquitous language, and drew a beautiful context map on the whiteboard. Six months later, half the codebase imports directly from the other half and your “bounded contexts” are a boundary in name only. The uncomfortable truth: a boundary you don’t enforce isn’t a boundary — it’s a suggestion. The fix is to make your architecture measurable and self-policing with architecture fitness functions and a couple of old-but-gold coupling metrics.

This is a practical guide to proving — in CI, on every commit — that your DDD boundaries are still holding, so drift fails the build instead of rotting silently for two quarters.

Walled bounded contexts kept decoupled by an automated fitness-function gate that blocks a forbidden cross-context link

🧪 Fitness functions: turn “the senior would’ve caught that” into “the build caught that”

A fitness function is an automated, objective test of an architectural characteristic — not “does this feature work” but “does the system still honor a structural rule we decided on.” Coined in Building Evolutionary Architectures, the idea is simple and powerful: encode your architectural decisions as executable checks that run in CI and fail the build on violation.

For DDD, the single highest-value fitness function is the boundary rule: “Code in the Billing context may not import from the Shipping context except through its published interface.” Written once as a test, it converts a rule that used to live in a senior engineer’s head (and got enforced inconsistently in review) into a deterministic gate that catches every violation, from every contributor — human or AI agent — on every commit.

That’s the whole game: architecture stops being a diagram people ignore and becomes a property the build guarantees.

🛠️ The tools, by language

You don’t build this from scratch — every major ecosystem has a dependency-rule tool:

  • ArchUnit (Java/Kotlin) — write architecture rules as plain unit tests (“no class in ..billing.. may depend on ..shipping..“).
  • Deptrac (PHP) — declare layers/contexts and the allowed dependencies between them; it fails on any violation.
  • import-linter (Python) — define “contracts” (forbidden imports, layered architectures) enforced in CI.
  • NetArchTest (.NET) — fluent assertions about type dependencies in test form.
  • go-arch-lint (Go) — a config-driven component dependency linter.
A CI gate blocking a forbidden cross-context dependency in red while an allowed one passes green

Pick the one for your stack, express your context map as its rules, and wire it into CI next to your unit tests. A cross-context import that used to slip through now turns the pipeline red.

📐 Coupling metrics: the numbers behind “decoupled”

Fitness functions catch hard violations. Metrics tell you whether a context is drifting toward trouble before it breaks a rule. Robert C. Martin’s package metrics are the classic, still-useful lens:

  • Afferent coupling (Ca) — how many things depend on this context (incoming). High Ca means lots of others rely on you: you’re stable, and changing you is expensive.
  • Efferent coupling (Ce) — how many things this context depends on (outgoing). High Ce means you’re at the mercy of many others.
  • Instability I = Ce / (Ca + Ce) — ranges 0 (maximally stable, everyone depends on you, you depend on no one) to 1 (maximally unstable). Neither extreme is “bad”; the point is that stable packages should be abstract and unstable ones concrete.
  • Abstractness (A) — the ratio of abstract types to total types in the context.
  • Distance from the Main Sequence D = |A + I − 1| — the headline number. Martin’s insight is that healthy components sit near the line A + I = 1: stable and abstract, or unstable and concrete. Drift far off it and you land in one of two bad zones — the Zone of Pain (stable and concrete: everyone depends on it, but it’s rigid and hard to change) or the Zone of Uselessness (abstract but nobody uses it).
Components plotted near a main-sequence line with two flagged corner zones of pain and uselessness

You don’t need to obsess over these daily. You need to snapshot them over time and watch the trend: a core bounded context whose afferent coupling keeps climbing and whose distance D is creeping into the Zone of Pain is telling you, quantitatively, that it’s becoming a bottleneck the whole system is stuck to.

📉 Detecting drift before it compounds

Boundaries erode one “just this once” import at a time. Three habits keep that in check:

  1. Block new violations in CI. The fitness function is the gate — a new cross-context dependency can’t merge. This is the single most important control.
  2. Snapshot metrics per release. Track Ca/Ce/D per context over time so slow erosion shows up as a trend line, not a surprise.
  3. Govern the context map. Treat the allowed dependencies between contexts as a reviewed artifact (it’s literally the config for your dependency-rule tool). Changing what’s allowed is an architectural decision that gets reviewed — not something that happens silently because someone added an import.

If you’re running a fleet of AI coding agents, this matters double: agents will cheerfully wire two contexts together to make a feature work, because a diff-level view can’t see that the change is architecturally wrong. The fitness function is what stops them — the same “context is probabilistic, configuration is deterministic” principle behind the rest of our agentic-loops work. See mutation testing for AI-generated code for the test-quality half of the same story, and DDD for AI coding agents for why bounded contexts are the agent’s natural work-unit.

⚠️ Honest caveats

  • Don’t let the gate kill velocity. Start with the one or two boundary rules that matter most; a wall of pedantic architecture tests trains people to ignore them.
  • Metrics are signals, not verdicts. A high instability number isn’t a bug — a concrete, unstable adapter should be unstable. Read the metrics in context, not as pass/fail.
  • Governance has a cost. Maintaining the allowed-dependency config and reviewing changes to it is real work; budget for it, and keep the rules few and meaningful.

❓ Frequently Asked Questions

What is an architecture fitness function? An automated, objective test of an architectural characteristic — like “no cross-context imports” or “the domain layer may not depend on the web layer” — that runs in CI and fails the build when the rule is violated. It turns architectural intent into an enforced gate.

How do I enforce bounded-context boundaries in code? Use a dependency-rule tool for your stack — ArchUnit (Java), Deptrac (PHP), import-linter (Python), NetArchTest (.NET), or go-arch-lint (Go) — to declare which contexts may depend on which, and run it in CI so any forbidden import fails the pipeline.

What is the “distance from the main sequence”? D = |A + I − 1|, where A is abstractness and I is instability. It measures how far a component is from the ideal balance of “stable and abstract” or “unstable and concrete.” Large distances land you in the Zone of Pain (rigid but depended-on) or the Zone of Uselessness (abstract but unused).

Are coupling metrics worth tracking for DDD? Yes, as a trend. Snapshotting afferent/efferent coupling and distance-from-main-sequence per context over time reveals boundary erosion before it becomes a crisis — but treat the numbers as signals to investigate, not automatic verdicts.

📚 Further Reading

  • What Is Domain-Driven Design? — the concepts these metrics protect
  • Domain-Driven Design for AI Coding Agents — why boundaries matter more with agents
  • Mutation Testing for AI-Generated Code — the test-quality gate that pairs with these architecture gates

📚 Recommended Resources

Disclosure: some links below are Amazon affiliate links. If you buy through them, I earn a small commission — at no extra cost to you — which helps keep this site running.

Enforcing architecture is equal parts DDD and evolutionary-architecture discipline. These build both.

  1. Building Evolutionary Architectures (2nd ed.) — Ford, Parsons, Kua & Magee · Book. The source of the fitness-function idea — how to make architectural governance automated and continuous.
  2. Learning Domain-Driven Design — Vlad Khononov · Book. Where the bounded contexts you’re measuring come from — strategic design done approachably.
  3. A Philosophy of Software Design — John Ousterhout · Book. Deep vs. shallow modules and complexity — the design taste behind low coupling.
  4. Clean Architecture — Robert C. Martin · Book. The source of the coupling metrics (Ca/Ce/instability/main sequence) this article uses.
  5. Accelerate: The Science of Lean Software and DevOps — Forsgren, Humble & Kim · Book. Why measuring the right architectural signals beats optimizing gameable proxies.

Newsletter

Tags

Agentic AI Agentic Development AI AI Agents AI Coding Agents Artificial intelligence Backlinks Blockchain Bounded Context Browser ChatGPT Plugins Claude Code CLPR Context Engineering Cross-Chain Cryptocurrency Developer Tools Distributed Systems DLT Domain-Driven Design Email Google Search HBAR Hedera Hedera Hashgraph Internet LLM Machine Learning MCP Microservices Model Context Protocol News NLP Orchestration Photoshop Productivity Saga Pattern SEO Smart Contracts Software Architecture software engineering Twitter Typescript Web3 Writing

Recent Articles

  • Visual Search Explained: From Google Lens to Shop-the-Look October 6, 2026
  • What a Podcast “Download” Actually Proves October 6, 2026
  • Diffusion vs CNN vs Transformer: What’s Different? October 6, 2026
  • V8 Sandbox Security: Why a Memory-Safe Language Would Not Fix V8 October 5, 2026
  • Cardano Governance Explained: How the Community Takes the Wheel October 5, 2026
  • What Are World Models in AI? A Complete Guide October 5, 2026

Copyright © 2026 · News Pro Theme On Genesis Framework · WordPress · Log in

Content on this site is produced with the assistance of Large Language Models and edited by a human. It is intended for educational purposes — facts may occasionally be incorrect. If you spot an error, please email Larionovdmitri@learninternetgrow.com.

Affiliate Disclosure: This site contains affiliate links to Amazon and other partners. If you purchase through these links, LearnInternetGrow.com may earn a commission at no additional cost to you. We only recommend products we genuinely believe in.

Privacy Policy · Terms of Service