When using OOP/SOLID Development principles, Dependency Injection gets messy. Either you have the top-level entry points managing dependencies for multiple levels below themselves and passing dependencies recursively through construction, or you have somewhat duplicate code in factory/builder patterns and interfaces that build dependencies as you need them. There
There is no OOP/SOLID way to perform this andAND have super pretty code.
If therethat previous statement is no OOP/SOLID way to do it manually (without sacrificing some slight prettiness)true, then how do IOC Containers do it? I’ll give you a hint: They As far as I know, they aren’t employing some secretunknown technique we’ve never heard ofthat can't be done with manual D. They’re breakingI. So the only explination is that IOC Containers break OOP/SOLID Principles by altering code behind the scenes (or at compile-time) to make private accessors andusing static objects private accessors.
Do IOC Containers break the following principles behind the scenes? This is the real question since I have a good understanding, but have a feeling somebody else has a better understanding:
- Scope controlScope control. Scope is the reason for nearly every decision I make on my code design. Block, Local, Module, Static/Global. Scope should be very explicit, as much at block-level and as few at Static as possible. You should see declarations, instantiations, and lifecycle endings. I trust the language and GC to manage scope as long as I’m explicit with it. In my research I’ve found that IOC Containers set up most or all dependencies as Static and control them through some AOP implementation behind the scenes. So nothing is transparent.
- EncapsulationEncapsulation. What is the purpose of encapsulation? Why should we keep private members so? For practical reasons it is so implementors of our API can’t break the implementation by changing the state (which should be managed by the owner class). But also, for security reasons, it’s so injections can’t occur that overtake our member states and bypass validation and class control. So anything (Mocking frameworks or IOC frameworks) that somehow injects code before compile time to allow external access to private members is pretty huge.
- Single Responsibility PrincipleSingle Responsibility Principle. On the surface, IOC Containers seem to make things cleaner. But imagine how you would accomplish the same thing without the helper frameworks. You would have constructors with a dozen or so dependencies being passed in. That doesn’t mean cover it up with IOC Containers, it is a good thing! It’s a sign to re-factor your code and follow SRP.
- Open/ClosedOpen/Closed. Just like SRP isn’t Class-Only (I apply SRP down to single-responsibility lines, let alone methods). Open/Closed is not just a high level theory to not alter the code of a class. It’s a practice of understanding the configuration of your program and having control over what gets altered and what gets extended. IOC Containers can change the way your classes work altogether partially because: