Skip to content

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.