Why: the goal or problem

Business rules should outlive a database or interface. If they import those details, replacing either forces policy changes too.

How: work toward a solution

  1. Fictional single process: R1, A17 unsaved. HTTP/CLI controller maps IDs into SaveArticle; SavedArticle validates them.
  2. SaveArticle calls SaveRepository, implemented by memory/embedded-database adapters. Imports point inward: adapters → use-case contracts → domain; calls reach outward to storage. Only plain data crosses; ORM rows stay outside.
  3. Saved: 0 → 1 entries; repeat → 1. Empty IDs or failure before writing → 0; retry after correction.
Dependency direction is not call direction

Illustrative example

Dependencies point toward policy

R1 · A17 · initially unsaved

One process · dotted enclosure

1 · Frameworks & drivers

HTTP / CLI · Memory / Embedded database

↓ Source dependency

2 · Adapters

Controllers map IDs; storage adapters map records

↓ Source dependency

3 · Application policy

SaveArticle

Owns the SaveRepository interface

↓ Source dependency

4 · Domain policy

SavedArticle

Rejects empty reader/article IDs

At the storage boundary

← Source dependencySaveRepository (inside) ← storage adapter

Runtime call →SaveArticle → via SaveRepository → storage adapter (outside)

Plain IDs and Saved results cross the boundary; ORM rows stay outside. Four bands explain this example, not a required folder structure.

  • Save → repeat: 0 → 1 → 1 entries; return Saved.
  • From empty: empty IDs or failure before writing → 0. Retry after correction.

HTTP / CLI and memory / embedded database are alternatives; no data migration is implied.

What: the concept

Clean architecture directs source dependencies toward policy. Runtime calls can travel outward through inward-owned interfaces. Martin

Mapping costs maintenance. Combine with hexagonal ports. Four folders are not mandatory.