Skip to main content

Layering & dependencies

Layering is not diagram theater—it constrains dependency direction: inner layers must not know outer ones; domain logic must not depend on framework details. The structure below works in monoliths, modular monoliths, and multi-service setups.

Four logical layers

LayerResponsibilityMay depend on
PresentationHTTP/UI/CLI, serialization, auth entryApplication interfaces
ApplicationUse-case orchestration, transactions, DTO mappingDomain
DomainEntities, value objects, invariantsNo infrastructure
InfrastructureDB, queues, third-party SDKsImplements ports defined inward

Rule: dependencies point inward (presentation → application → domain; infrastructure implements ports, domain does not import adapters).

[ UI / API ] → [ Use cases ] → [ Domain ]

[ Adapters: DB, MQ, HTTP client ]

Mapping to Clean / Hexagonal

TermLayer here
Entity / domain modelDomain
Use case / interactorApplication
Controller / presenterPresentation
Gateway / repository implInfrastructure adapter

Define ports on the inner side; implement adapters outside. Swapping DB or UI framework should touch adapters, not business rules.

Monolith vs modular monolith vs services

ShapeWhenLayering note
MonolithSmall team, exploration, strong local transactionsEnforce deps with packages/targets (ArchUnit, SwiftPM)
Modular monolithMedium scale, separate compile/testTiny public api per module
ServicesIndependent scale/deployThinner layers; contracts replace in-process calls
tip

Default: modular monolith + sharp boundaries; split services on deploy cadence, scaling, or failure isolation—not on org chart alone.

Violations and fixes

ViolationEffectFix
Domain imports ORM annotationsStorage change ripples everywhereRepository port + infra mapping
Controller owns rulesDuplication, hard testsApplication/domain services
Cross-layer DTO leakAPI churn breaks internalsMap at boundaries
Shared “util” imported everywhereHidden global couplingPorts or single adapter

Testing by layer

LayerTestsGoal
DomainPure unitInvariants, state machines
ApplicationUse-case with fakesOrchestration, transactions
InfrastructureIntegrationReal SQL/broker (containers OK)
PresentationContract / sampled E2EHTTP schema, critical paths