← Blog'a Dön
TECHNICAL

What Is Dependency Injection? Clean Code & Testability Guide

F. Çağrı Bilgehan27 Ocak 202610 dk okuma
dependency injectionsoliddesign patterntesting

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

  1. Constructor Injection (recommended) — Dependencies via constructor
  2. Setter Injection — Dependencies via setter methods
  3. 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

  1. Depend on interfaces — Not concrete classes
  2. Prefer constructor injection — Most explicit and testable
  3. Limit dependencies — 3-5 ideal, 7+ means split the class
  4. Use IoC containers for large projects
  5. 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.

İlgili Yazılar

How to Build a SaaS Product: A Starter Guide

What is SaaS, how is it built, and what steps should you follow for a successful SaaS product? Technology selection, pricing, and MVP strategy guide.

No-Code and Low-Code: Build Apps Without Coding

What are no-code and low-code platforms, what are their advantages, and when should you use them? Comparing Bubble, Webflow, Retool, and Airtable.