What Is Dependency Injection? Clean Code & Testability Guide
Are your classes tightly coupled? Is testing hard? Does changing the database affect all your code? Dependency Injection provides dependencies from the outside, enabling flexible and testable code.
What Is DI?
Dependency Injection (DI) means a class receives its dependencies rather than creating them. It's the practical application of SOLID's Dependency Inversion Principle.
Without DI (Tight Coupling)
class OrderService {
private db = new PostgresDatabase(); // Tight coupling!
private mailer = new SmtpMailer();
}
With DI (Loose Coupling)
class OrderService {
constructor(
private db: Database,
private mailer: Mailer
) {}
}
DI Methods
- Constructor Injection (recommended) — Dependencies via constructor
- Setter Injection — Dependencies via setter methods
- Interface Injection — Dependencies via interface contract
Why DI?
Testability
const service = new OrderService(new MockDatabase(), new MockMailer());
Flexibility
// Dev: SQLite + console
const dev = new OrderService(new SqliteDb(), new ConsoleMailer());
// Prod: Postgres + SMTP
const prod = new OrderService(new PostgresDb(), new SmtpMailer());
IoC Containers
Automate dependency management in large projects:
// NestJS
@Injectable()
class OrderService {
constructor(
private readonly db: DatabaseService,
private readonly mailer: MailerService,
) {}
}
| Language | Container | |----------|-----------| | TypeScript | NestJS, InversifyJS | | Java | Spring | | C# | .NET DI, Autofac |
Anti-Patterns
- ❌ Service Locator (hidden dependencies)
- ❌ Over-injection (7+ dependencies = SRP violation)
- ❌ Injecting concrete classes instead of interfaces
Best Practices
- Depend on interfaces — Not concrete classes
- Prefer constructor injection — Most explicit and testable
- Limit dependencies — 3-5 ideal, 7+ means split the class
- Use IoC containers for large projects
- Avoid circular dependencies
Conclusion
DI is foundational for clean, testable, flexible code. Provide dependencies externally, decouple your classes, and use IoC containers for larger projects.
Learn DI and SOLID principles on LabLudus.