पाठ 18 / 25
Dependency Inversion and Dependency Injection
Depend on abstractions and inject collaborators instead of creating them.
High-level policy should not depend on low-level details
The Dependency Inversion Principle (DIP): high-level modules (business rules such as OrderService) should not depend on low-level modules (a specific database or SMS provider); both should depend on abstractions (interfaces), and abstractions should not depend on details. In practice, OrderService depends on an OrderRepository interface, and JdbcOrderRepository implements it. Dependency injection (DI) is the technique that makes this work: instead of a class creating its collaborators with new, they are passed in, usually through the constructor. This makes dependencies explicit, lets you substitute fakes or mocks in tests, and lets configuration choose implementations. Frameworks such as Spring, Jakarta CDI, Dagger, Guice and ASP.NET Core automate the wiring, but DI does not require a framework: passing objects into constructors in a main method is DI too. Prefer constructor injection with final fields over field injection, so objects are always fully initialised.
Constructor injection without a framework
OrderService depends only on interfaces; main wires real implementations, tests wire fakes.
public interface OrderRepository { void save(Order order); }
public interface Notifier { void orderPlaced(Order order); }
public final class OrderService {
private final OrderRepository repository;
private final Notifier notifier;
public OrderService(OrderRepository repository, Notifier notifier) { // injected
this.repository = repository;
this.notifier = notifier;
}
public void place(Order order) {
order.validate();
repository.save(order);
notifier.orderPlaced(order);
}
}
// production wiring
var service = new OrderService(new JdbcOrderRepository(dataSource), new SmsNotifier(smsClient));
// test wiring
var repo = new InMemoryOrderRepository();
var testService = new OrderService(repo, order -> { /* record call */ });new is a hard-coded dependency
Every new ConcreteThing() inside business logic fixes that dependency forever and makes testing harder. Create objects at the edges (main, configuration, factories) and pass them inward.
त्वरित जाँच: What does the Dependency Inversion Principle recommend?
- Both high-level and low-level modules should depend on abstractions
- High-level modules should create low-level modules directly
- All classes should be static
- Avoid interfaces to reduce code
Answer
Both high-level and low-level modules should depend on abstractions — DIP inverts the dependency so business logic depends on interfaces, not concrete details.