Card 01/ 05

ConceptDifficulty: Beginner1 min

Why a Hard-Coded Dependency Is Expensive to Change

RideService needs a place to look rides up. Somewhere inside it, a line reads new PostgresRideRepository(), and from that moment RideService and Postgres are one thing — you cannot have one without the other, in production or in a test.

java
class RideService {
    private final PostgresRideRepository repository = new PostgresRideRepository();

    Ride getRide(String id) {
        return repository.findById(id);
    }
}

A test for getRide now needs a real, reachable Postgres database, because that one line leaves no other way in. Swap the database for a different provider later, and every class that does this gets edited, not just the one that talks to the database directly.

The fix has a name for the problem and a name for the solution. Inversion of Control is the principle: something other than the class itself decides which object it works with. Dependency Injection is the technique that carries it out — handing a class its dependency, usually through the constructor, instead of letting the class construct it. In a Spring application, the thing that does the handing is called the container.

So a class stops choosing its own dependencies and starts declaring what it needs — which is the one change that makes it testable with nothing real running behind it.