पाठ 9 / 25
Dependency Injection as a Pattern
Pass dependencies in instead of reaching out for them.
Inversion of control in practice
Intent: a component receives its collaborators from outside (usually through its constructor) instead of creating or looking them up itself. This applies the dependency inversion principle: CheckoutService depends on a PaymentGateway interface, and the composition root decides whether that is a real provider or a fake. Benefits: explicit dependencies, easy testing with fakes, and swapping implementations without editing the class. Manual DI (wiring with new in one startup file) is enough for many apps. DI containers automate the wiring and lifetimes (singleton, per-request, transient); examples include Spring in Java, the built-in container in ASP.NET Core, Angular's injector, and NestJS or InversifyJS in TypeScript. Avoid using a container as a service locator that classes call directly, which hides dependencies again.
Constructor injection and a test fake
Manual DI with a composition root.
interface PaymentGateway {
charge(customerId: string, amountCents: number): Promise<{ ok: boolean; id?: string }>;
}
class CheckoutService {
constructor(
private payments: PaymentGateway,
private orders: OrderRepository,
) {}
async checkout(cart: Cart) {
const result = await this.payments.charge(cart.customerId, cart.totalCents);
if (!result.ok) throw new Error('Payment declined');
return this.orders.create(cart, result.id!);
}
}
// Composition root (main.ts): the only place that picks implementations
const checkout = new CheckoutService(new CardProviderGateway(apiKey), new SqlOrderRepository(pool));
// In a test: a fake, no network
const fakePayments: PaymentGateway = { charge: async () => ({ ok: false }) };
const service = new CheckoutService(fakePayments, new InMemoryOrderRepository());
await expect(service.checkout(cart)).rejects.toThrow('Payment declined');A chef and a supplier
A chef who grows every ingredient personally cannot change suppliers. A chef who has ingredients delivered can switch from one farm to another, or practise with plastic vegetables, without changing how they cook.
त्वरित जाँच: What is the "composition root" in dependency injection?
- A global variable holding every object
- The base class of all services
- The single place, usually at startup, where concrete implementations are created and wired together
- The first database table created
Answer
The single place, usually at startup, where concrete implementations are created and wired together — Wiring happens once, at the edge of the application.