Use this page when a term feels familiar but its boundaries are not clear. The three terms people often mix up are separated first: dependency injection is about wiring, inversion of control is about direction, and dependency inversion is about shape.
| Term | Kind of thing | One line |
|---|---|---|
| Dependency Injection | Technique (wiring) | Objects receive their dependencies from outside instead of creating them. |
| Inversion of Control | Principle (direction) | A caller or framework controls when your code runs. The rule is "Do not call us; we will call you." |
| Dependency Inversion | Principle (shape) | High-level and low-level modules depend on abstractions rather than on each other's concrete details. |
DIP in the Wild describes DI as wiring, IoC as direction, and DIP as shape.
- Abstraction what, not which
-
A description of what is needed without choosing a particular provider.
In TypeScript, this is often an
interfaceor a function type."An abstraction names the capability I need; the wiring decides who provides it."
- Composition root wire in main, not in the middle
-
The single place, as close as possible to the application entry point,
where concrete dependencies are selected and objects are assembled. The
application logic and libraries do not choose the concrete classes; the
entry point does.
"Dependencies are composed at the edge of the app, so the rest of the code does not need to construct them." See Seemann and van Deursen's chapter 1 for the composition-root practice.
- Constructor injection needs to go in the parentheses
-
Passing dependencies as constructor parameters. The dependency list is
visible in the signature, and a half-built object is harder to create.
"If it is on the constructor, the type system enforces it. You cannot forget to provide it."
- Coupling change travels
-
How much one module must know about another, and how far a change in one
forces changes in the other. Tight coupling names concrete details;
loose coupling agrees on a small abstraction.
"Coupling is the distance a change travels. Loose coupling lets the change stop at the wiring."
- Dependency a need you do not own
-
Something a module needs to do its job but does not control: another
object or service, a function,
fetch, the system clock, orlocalStorage. If it can change, fail, or need replacing without the module's logic changing, it is a dependency rather than an owned detail."A dependency is anything the module needs but should not decide for itself."
- Dependency Inversion Principle (DIP) abstractions, not concretions
-
High-level and low-level modules both depend on abstractions. The
details point toward the abstraction owned by the policy instead of
forcing the policy to point at concrete details.
"DIP flips the arrow. Details depend on the abstraction my code defines."
- Dependency Injection (DI) give, do not take
-
A wiring technique in which objects receive dependencies from outside,
through a constructor, setter, or parameter, instead of constructing or
fetching them. It needs no framework. Martin Fowler named the pattern in
his 2004 article on dependency injection.
"DI means dependencies are supplied from outside, so behaviour can change without editing the class."
- Fake a working stand-in
-
A lightweight working implementation used in tests. A fake transport can
return canned values without making a network request. It lets the test
exercise the service logic rather than the infrastructure. Unlike a
mock, a fake usually focuses on providing working behaviour instead of
asserting how the dependency was used. See
Kent C. Dodds's discussion of fakes
.
"I inject a fake so the test exercises my code, not the network."
- Hollywood Principle do not call us...
-
"Do not call us; we will call you." It is the slogan for inversion of
control: your code registers or supplies behaviour, while another caller
decides when to run it.
"A framework calls my code; my code does not drive the framework."
- Injection the delivery itself
-
The act of handing a dependency to the code that needs it. Constructor,
setter, property, and parameter injection are different delivery
choices. Passing a dependency through component props is parameter
injection; constructor injection is the default in this course.
"Injection is delivery. Where you deliver it is a design choice; constructor is the default."
- Interface a structural contract
-
A TypeScript construct that describes a value's shape. TypeScript is
structurally typed, so an object with the right shape can satisfy an
interface. An interface disappears at runtime.
"A TypeScript interface is a compile-time contract, not a runtime lookup token."
- Inversion of Control (IoC) who drives?
-
A broad principle in which control over program flow or object creation
moves from your code to an external framework or caller. Frameworks are
its everyday example. Dependency injection is one technique within IoC.
"IoC asks who is driving. If it is not my code, control is inverted."
- IoC container / DI container a factory with a map
-
A library that maps tokens to providers and constructs an object graph.
Examples include Angular's injector, tsyringe, and InversifyJS. A
container can automate a composition root, but it is never required for
dependency injection. Containers are outside the main line of this
course.
"A container automates the composition root; it does not change what DI is."
- Service does one job well
-
A reusable object dedicated to one responsibility, such as data access,
logging, or notifications. A service is often the module that receives a
dependency. In Angular, a service can be registered for injection. See
the Angular documentation.
"A service is a unit of behaviour other code depends on."
- Service Locator the anti-pattern next door
-
An object that code asks for dependencies at runtime, such as
locator.get(PaymentApi), instead of receiving them. It hides dependencies from signatures, forces code to depend on the locator, and defers failures to runtime. See Fowler's discussion of DI and Service Locator for the comparison."A locator pulls. DI pushes. Pushing keeps dependencies visible in the constructor."
- Test double stunt double for a dependency
-
An umbrella term for something standing in for a dependency during a
test: a fake provides working behaviour, a stub returns canned answers,
a spy records calls, and a mock asserts interactions. The distinctions
describe the role the stand-in plays, not a different injection
technique. See
Vitest's mocking guide.
"Test doubles let tests swap injected dependencies without touching production code."
- Token the key in the map
-
The key a container uses to look up a dependency. In Angular, this may be
a type or a dedicated
InjectionToken. A token must exist at runtime, which is why a plain TypeScript interface is not enough for a container lookup."A token is the lookup key. In TypeScript it must exist at runtime, so a plain interface is not enough for a container."
- Wiring choosing the real ones
-
Selecting concrete dependencies and connecting them to the objects that
need them. Wiring belongs at the
composition root, not in the middle of
application logic.
"Wiring is where policy meets plumbing. It is the one place concrete classes are named."
Glossary citations
- Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern . It covers DI, injection forms, and Service Locator.
- Martin Fowler: InversionOfControl . It explains IoC and the Hollywood Principle.
- Robert C. Martin: The Principles of OOD . It defines DIP.
- Brett L. Schuchert: DIP in the Wild . It explains the wiring, direction, and shape framing.
- Mark Seemann and Steven van Deursen: Dependency Injection Principles, Practices, and Patterns, chapter 1 . It covers composition roots and Pure DI.
- Kent C. Dodds: Stop mocking fetch . It explains the use of hand-written fakes in browser tests.