Skip to the content.

Dependency Inversion Principle

High-level policy should not depend on low-level detail; both depend on abstractions.

The violation

The business logic constructing its own infrastructure:

class OrderService {
    private final StripeGateway stripe = new StripeGateway("sk_live_...");
    private final PostgresOrderStore db = new PostgresOrderStore("jdbc:...");
    // Testing placeOrder() now needs Stripe credentials and a database.
    // Switching payment provider means editing the business logic.
}

The policy (what placing an order means) is welded to mechanisms (Stripe, Postgres). The dependency arrows point the wrong way: the most important code in the shop depends on the most replaceable.

The fix

OrderService depends on two abstractions it owns – PaymentGateway and OrderRepository – and receives implementations through its constructor, returning a PlacedOrder. Concrete details like InMemoryOrderRepository implement the interfaces at the edge. This inversion is exactly what a DI container (Spring) automates – but the principle is just constructors and interfaces, no framework required.

Benefits

Example test

OrderServiceDipTest