Description
DI strategy comparison: constructor, setter, service locator with evaluation matrix and anti-pattern detection.
Dependency injection is the most misunderstood pattern in software engineering. Most teams use it because 'best practices' say so, without understanding why or when. This framework evaluates injection strategies by coupling, testability, and discoverability. STEP 1 — THREE STRATEGIES - CONSTRUCTOR INJECTION: Dependencies declared as constructor parameters. Explicit, required, testable. Best for mandatory dependencies. The class cannot be instantiated without them—which is the point. Every missing dependency causes a compile-time error, not a runtime NullPointerException. - SETTER INJECTION: Dependencies set via setter methods after construction. Optional, mutable, allows circular dependencies. Best for optional dependencies with sensible defaults. Risk: partial initialization—the object graph may be incomplete at construction time, causing NullReferenceException at method-call time. - SERVICE LOCATOR: A registry returns dependencies by type/name. Minimal constructor changes, enables dynamic resolution. Worst: hides dependencies, makes testing impossible without mocking the locator, creates implicit coupling every class in the system can reach. STEP 2 — EVALUATION MATRIX | Criteria | Constructor | Setter | Locator | |----------|------------|-------|--------| | Explicit dependencies | ✓ All declared | ✗ Hidden in setters | ✗ Invisible | | Compile-time safety | ✓ Missing = error | ✗ Null at runtime | ✗ ClassCastException | | Testability | ✓ Mock in constructor | ✓ Mock via setter | ✗ Mock the locator | | Circular deps | ✗ Not possible | ✓ Allowed | ✓ Any order | | Optional deps | ✗ Requires overloads | ✓ Natural | ✓ Any | | Frameworks | Spring, Guice, Dagger | Spring, EJB | Java CDI, Laravel | STEP 3 — RECOMMENDATION RULES - 80% of classes: constructor injection. If a dependency is required for the class to function, it belongs in the constructor. - 15% of classes: setter injection. Optional caches, logging, metrics. Provide a no-arg constructor with sensible defaults. - 5% of classes: service locator. Only at system boundaries where the dependency graph is dynamic (plugin systems, feature-flag-gated services). Never in domain logic. STEP 4 — ANTI-PATTERN DETECTION - Field injection (@Inject on fields): Hidden dependencies, impossible to see without reading annotations. Constructor injection reveals everything in the constructor signature. - God constructor: 15+ constructor parameters. Split the class. A class that needs everything does too much. - Injection-framework coupling: Classes annotated with framework-specific DI annotations cannot be reused outside that framework. Write plain constructors, use framework configuration to wire them. OUTPUT: Strategy recommendation per class type, evaluation matrix, anti-pattern flags with fixes.
No comments yet. Be the first!