Dependency injection frameworks add confusion

Manual DI vs. Frameworks

  • Many agree with the article’s stance: start with manual DI (explicit construction at the top level) and only adopt a framework if real pain appears.
  • Critics say reflection/magic-based frameworks obscure wiring: object graphs become implicit, control flow is hidden, and you lose a “single place” to see how the system is assembled.
  • Some report real bugs caused by test DI configuration diverging from production, or by complex lifecycle rules (e.g., Spring/ASP.NET Core quirks like @Lazy and config injection).
  • Others argue DI frameworks are just automating object construction; you can get most benefits with straightforward code that wires dependencies in main or equivalent.

Language Ecosystems and Culture

  • In Go, DI containers are rare; people hand-wire dependencies or use global-ish configuration, and many see this as simpler and sufficient.
  • In Java and .NET, DI frameworks (Spring, Guice, Dagger, ASP.NET Core, Autofac, etc.) are mainstream. Some call Spring a “cancer”; others note it’s both extremely popular and a major improvement over pre-Spring Java.
  • Dynamic or monkey‑patch‑friendly languages (Python, JS/TS) often solve testability via module mocking rather than DI containers, reducing perceived need for frameworks.

Testability, Design, and Trade-offs

  • Pro-DI voices emphasize:
    • Easier unit testing via injected clocks, DB handles, etc.
    • Separation of “glue code” from business logic.
    • Managing lifecycles (singletons, per-request objects), cross-cutting concerns, and reducing tight coupling/statics.
    • Coding to interfaces and enabling multiple implementations.
  • Skeptics counter:
    • Manual DI or simple factory/static create() methods often suffice.
    • If wiring becomes painful, it may indicate an overgrown dependency graph that should be simplified, not hidden behind a container.
    • For small services and microservices, DI frameworks can be net harmful noise.

Tooling, Navigation, and “Magic”

  • A major complaint: DI frameworks break straightforward navigation and “grepability” (which implementation of Foo is this? where is it constructed?).
  • Supporters respond that modern IDEs (IntelliJ, Rider, VS, Android Studio) model DI graphs, show which implementation is injected, and even visualize bean graphs.
  • Critics argue relying on advanced IDE features is risky (e.g., debugging production at 3 a.m.) and that code should remain understandable with minimal tooling.

Terminology and Conceptual Confusion

  • Several note confusion between dependency injection, dependency inversion, and IoC.
  • Many see “dependency injection” as an intimidating or misleading label for “pass your dependencies as parameters,” suggesting alternatives like “dependency parameters.”
  • Some characterize DI frameworks as glorified global variables or service locators; others insist the value lies in explicit, testable wiring rather than runtime magic.