Dependency Design

Direction, inversion and injection — taught as three different ideas rather than one, because conflating them is how teams end up with a container and no boundaries.

Dependency Direction

Stable, high-level policy should not depend unnecessarily on volatile, low-level detail. The word "unnecessarily" is doing almost all the work.

Q · When module A and module B have to talk to each other, which one should know the other exists?
Dependency Inversion

Business policy defines the interface; infrastructure implements it. Both arrows point at the middle — and none of this requires a container.

Q · How do I let a business rule trigger an effect it must not know the mechanism of?
Dependency Injection

An object receives its collaborators instead of constructing them. That is the whole idea, it needs no library, and it is the third of three things people call DIP.

Q · Should an object build the things it needs, or be handed them?
Constructor Injection

Take collaborators as constructor parameters and the type system enforces that a constructed object is a usable one. No framework required, and the parameter count is a design signal.

Q · Of all the ways to hand an object its collaborators, which should be the default and why?
Service Locator

A global registry objects pull dependencies out of. It makes dependencies implicit — which defeats local reasoning and moves whole classes of error from compile time to run time.

Q · Why is asking a registry for a dependency worse than being handed it, when the object ends up with the same collaborator either way?
Wiring and the Composition Root

Somebody has to construct the object graph. Doing it in one deliberate place is the design decision; doing it with a container is a separate, later, optional one.

Q · If nothing constructs its own dependencies, who constructs anything — and where does that code live?
Volatile Dependencies

Only some dependencies are worth inverting: the ones that change, that are slow, that have side effects, or that are non-deterministic. The rest should be called directly.

Q · Which of the things this module depends on actually deserve an interface, and which should I just call?