CodeIntermediate

Why does the Dependency Rule point inward?

“Clean Architecture says source code dependencies must point inward, toward the domain. Why that direction? What goes wrong when it is broken, and how do you enforce it?”

What this tests

  • Understanding of dependency inversion as a mechanism, not a slogan
  • Concrete consequences of a domain that depends on frameworks
  • Enforcement in the build, not only in code review
  • Awareness that the rule has a cost

Answers by level

Read the beginner answer first and notice what is missing.

Direction matters because a dependency is a reason to change. If the domain imports the web framework, a framework upgrade can break business rules; if it imports the ORM, every entity carries persistence annotations and a query concern leaks into every rule. Pointing inward means the stable, slow-changing thing (the rules) is depended upon, and the volatile things (frameworks, drivers, transports) depend on it. Volatile depending on stable is the only arrangement where change stays local.

When it is broken the symptoms are specific: you cannot instantiate an entity in a test without a database connection; a use case returns the framework's response type; business validation lives in a controller so the same rule is implemented twice for the API and the queue consumer. Enforcement must be mechanical: a package structure where the domain has no dependencies declared, plus a build rule — an import-boundary lint, ArchUnit, Go internal/ — that fails when domain/ imports from infrastructure/.

The cost is the interface and the adapter for every outward call, which is why the rule is worth applying strictly only where there is enough domain to protect.

Green flags · Red flags

Strong green flag · Points out that the payoff is local change and fast tests, not the fantasy of swapping the database.
Green flags
  • Explains direction via stability: volatile depends on stable
  • Names dependency inversion and the composition root
  • Distinguishes runtime control flow from compile-time dependency
  • Gives concrete breakage symptoms (tests need a DB, rules duplicated in controllers)
  • Enforces with a build rule, not review
Red flags
  • "So we can swap Postgres for MongoDB later."
  • Thinks rings are folders and enforcement is convention
  • Cannot explain how the inner ring calls outward without depending outward
  • Applies the full ring structure to a thin CRUD service

Follow-up questions

F1
The use case must send an email. How, without importing the mail library?
F2
What is the composition root and where does it live?
F3
How do you detect a violation in CI?

Scenario

An entity class carries ORM annotations, a JSON serializer attribute and a validation decorator from the web framework. Upgrading the framework broke tax calculation. Explain which dependency direction is wrong, what the fix looks like in code, and how you would stop it from recurring.

Learn this topic