Module layout
Every bounded-context module follows the same layered hierarchy. Folder names may adapt to a host project (app/Modules, src/Modules, …), but the roles stay fixed.
Canonical tree
{Module}/
├── Application/ # Orchestrator
│ ├── DTO/{Capability}/ # Input DTOs from UI → Use Case
│ ├── Providers/ # Composition root (wiring only)
│ └── UseCases/{Capability}/ # First-level *UseCase + nested helpers
├── Domain/ # Pure business core
│ ├── DTO/ # Intra-module structured data (optional)
│ ├── Entities/
│ ├── Enums/
│ ├── Events/
│ ├── Exceptions/
│ ├── Ports/
│ │ ├── {Capability}/ # Persistence / local feature ports
│ │ ├── Acl/ # Consumer-owned outbound need ports
│ │ └── Module/ # This module’s outbound façades
│ └── ValueObjects/
├── Infrastructure/ # Adapters
│ ├── Config/
│ ├── ExternalServices/ # ACL adapters to peers / HTTP
│ ├── Persistence/ # Framework-specific drivers + mappers
│ └── ExternalApi/ # Third-party vendors (optional)
└── UI/ # Delivery
├── Controllers/
├── Requests/ (or equivalent validation)
├── Routes/
└── Presenters / Resources
{Capability} is a documentation placeholder (e.g. Order/, Fulfillment/). Never create a directory literally named Feature.
Layer roles
| Layer | Owns | Must not own |
|---|---|---|
| Domain | Entities, ports, events, domain DTOs, invariants | Framework types, peer modules, Application |
| Application | Use Cases, Application DTOs, composition root wiring | Business policy hidden in providers; foreign Domain |
| Infrastructure | Port implementations, mapping, ACL, queues | Policy that belongs in Domain/Use Cases |
| UI | HTTP/CLI/admin entry, validation of shape, response mapping | Eligibility / reservation / peer rules |
Dependency direction
UI / Infrastructure → Application → Domain
- Application may depend on Domain (same module) + promoted Shared kernel ports.
- Domain never depends on Application, Infrastructure, UI, or other modules.
- Infrastructure and UI may depend on Application and Domain of the same module.
Shared kernel (preview)
Technical capabilities used by two or more modules may be promoted to a Shared kernel (Shared/ or equivalent). Business concepts never live in Shared — use ACL or Events.
Details: Shared kernel.
Same-module isolation
✅ Ordering Application → Ordering Domain
✅ Ordering Application → Ordering Application (sibling helpers)
❌ Ordering Application → Warehouse Domain / Application
❌ Ordering Domain → Warehouse Domain / Application
❌ Ordering Domain → Ordering Application
Next: strictness ladder.