# Dependency Inversion and Dependency Injection — Object-Oriented Programming (OOP)

Source: https://www.skillbyai.com/en/oop/s-dip

> 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.

```java
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.

**Quiz:** What does the Dependency Inversion Principle recommend?

- [x] 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.
