intermediate

Dependency injection

Pass collaborators from the outside so code depends on abstractions, tests can replace boundaries, and object creation stays separate from behavior.

Dependency injection supplies collaborators from outside the class—constructor parameters, factory, or DI container—so the class depends on abstractions and tests can substitute fakes. Object creation stays at the composition root; business code focuses on behavior.

Constructor injection makes required dependencies explicit; avoid service locators and hidden globals.

On interviews: wire a `OrderService` with injected `PaymentGateway` and show the unit test with a fake gateway.

Common pitfalls: containers everywhere without understanding graphs, injecting concrete SDK types into domain, and optional dependencies silently null.

The trade-off is setup ceremony versus testability and replaceable infrastructure.

Checklist:

  • Inject interfaces at constructor.
  • Compose objects at application boundary.
  • No static hidden dependencies in domain.