08 — Boundaries, Ports & Dependency Direction¶
Driving question: How can a system depend on frameworks and infrastructure without letting them define the core design?
Learning objectives¶
- Use ports/adapters to separate policy from mechanism.
- Explain dependency inversion at architecture scale.
- Identify boundary leakage through data types and exceptions.
- Compare layered, hexagonal, onion, and clean-style architectures critically.
Boundary intent¶
A boundary protects a design decision from volatility elsewhere. Ports and adapters are useful when they create a stable protocol between policy and mechanism.
graph LR
UI[UI Adapter] --> P[Application Port]
DB[DB Adapter] --> Q[Persistence Port]
P --> CORE[Domain / Policy]
Q --> CORE
The arrows in the source dependency graph need not match runtime call direction.
Leakage checklist¶
A boundary may be nominal rather than real if core code still imports:
- ORM annotations;
- framework request/response types;
- vendor exceptions;
- serialization-specific objects;
- infrastructure configuration.
Design / research exercise¶
Inspect a project that claims to use Clean/Hexagonal Architecture. Count core-module imports from infrastructure/framework packages. Classify each dependency as justified, accidental, or boundary leakage.
Suggested reading¶
- Alistair Cockburn on Hexagonal Architecture.
- Robert C. Martin on dependency boundaries.