Skip to main content

Dependency Injection vs. Dependency Inversion

Hard

Interview Question: "Everyone throws around the terms Dependency Injection, Dependency Inversion, and Inversion of Control. Are they the same thing? What are the three types of DI, and why is field injection considered an anti-pattern?"

The Quick Answer​

"Dependency Inversion (DIP) is the high-level SOLID principle stating that high-level modules should depend on abstractions (interfaces) rather than concrete classes. Dependency Injection (DI) is the design pattern used to deliver those dependencies from the outside. Inversion of Control (IoC) is the overarching architectural framework paradigm where the framework manages the lifecycle and flow of control."



The Three Types of Dependency Injection​

Interviewers frequently ask you to evaluate the 3 mechanisms of dependency injection:

Injection TypeHow It WorksVerdict
1. Constructor InjectionDependencies are passed as parameters into the constructor.Best Practice. Enforces complete object initialization, enables immutable (final) fields, and allows straightforward POJO unit testing without frameworks.
2. Setter InjectionDependencies are supplied through public setter methods.Use with Caution. Suitable for optional or reconfigurable dependencies, but leaves objects vulnerable to NullPointerException if called before setters run.
3. Field InjectionAnnotating private fields directly with @Autowired via reflection.Anti-Pattern. Hides dependencies, breaks plain unit testing (requires reflection or container), and masks circular dependencies until runtime.

The ELI5 Analogy: The Formula 1 Driver​

  • Without DI (Using new inside): Imagine an F1 driver who is hardcoded to manufacture their own car. Before racing, the driver must weld the chassis and attach slick tires. If it starts raining, the driver is helpless—they are permanently glued to the dry-weather tires they manufactured.
  • With DI: The driver simply declares: "I need a Vehicle to race." The pit crew assembles the car outside with rain tires and hands it to the driver. The driver focuses purely on racing logic without coupling to tire manufacturing.

The Distinction: DIP vs. DI vs. IoC​

ConceptNatureRole in Architecture
Dependency Inversion (DIP)Architectural PrincipleThe Goal: Mandates what the system should look like (high-level code depends on interfaces, not implementations).
Dependency Injection (DI)Design PatternThe Mechanism: The technique of how we achieve DIP (passing dependencies into a class).
Inversion of Control (IoC)Framework ParadigmThe Engine: The runtime container (e.g., Spring ApplicationContext, NestJS) that automatically resolves and wires dependencies together.

Clean Code Example​

Here is how constructor dependency injection enables flexible swapping and easy unit testing across languages:

// 1. Abstraction (DIP)
interface Database {
void save(String data);
}

class PostgresDatabase implements Database {
@Override
public void save(String data) {
System.out.println("Saved to Postgres: " + data);
}
}

// 2. Class depends on interface; receives it via Constructor Injection
class PaymentProcessor {
private final Database database; // Immutability guaranteed

public PaymentProcessor(Database database) {
this.database = database; // Injected from outside
}

public void process(String transaction) {
database.save(transaction);
}
}

// Usage in tests: easy to inject a MockDatabase without a framework