4 ms·
> Any kind of injection of dependencies should be done via an explicit method/constructor parameter. I would go further and always recommend manual DI - that i
by mateuszf 7y ago
> Any kind of injection of dependencies should be done via an explicit method/constructor parameter.
I would go further and always recommend manual DI - that is passing the objects and creating them in code rather than depending on some magic framework to do the job. That makes understanding / analyzing / fixing bugs a lot easier.
It's actually not that hard / boilerplate-y to do even in Java (which is what we do in our team).
- username3 7y agoDo you have code examples of this?
- mateuszf 7y agoWell, you just create an object and set it as a field / pass it via constructor to the object that uses it. There are dependency injections frameworks, but the term dependency injection doesn't mean injecting automatically, it's more general. It just means that the dependency is provided from outside, and not how it's done. https://en.wikipedia.org/wiki/Dependency_injection https://en.wikipedia.org/wiki/Dependency_injection
- jcelerier 7y ago> I would go further and always recommend manual DI - that is passing the objects and creating them in code rather than depending on some magic framework to do the job. That is so weird. The reason why we have DI and DI frameworks is because we are asked in requirements to make things configurable out-of-code (and at runtime), because someone wants to use a pretty UI or a config file of sorts to set up which behaviour is used to do $thing.
- dvdcxn 7y agoWhat's weird about it? In practice it just means writing classes which instead of newing things inside the constructor, allows them to be passed in by the caller. This is a pretty fundamental aspect of polymorphism and composition.
- jetcata 7y agoAgree, it reduces boilerplate and prevents you from shooting yourself in the foot when it comes to writing testable code.
- deleted 7y ago[deleted]
- jcelerier 7y ago> What's weird about it? What I meant about weird was that OP's proposed "solution" to DI is to "do it manually", while the exact reason while we want DI in the first place is not to do it manually (or, in the way that I heard it most in my life, "to be able to change it without rebuilding")
- dvdcxn 7y agoImo, dependency injection frameworks are distinct to the concept of DI. They do not represent DI itself, which is just a design pattern.
- mateuszf 7y ago> What I meant about weird was that OP's proposed "solution" to DI is to "do it manually", while the exact reason while we want DI in the first place is not to do it manually (or, in the way that I heard it most in my life, "to be able to change it without rebuilding") No, the main reason we want DI is to change the behaviors based on what's passed. That's dependency injection. Framework passing the dependencies is automatic dependency injection and what I'm advocating against.
- jcelerier 7y ago> No, the main reason we want DI is to change the behaviors based on what's passed. but which behaviours are passed depend on something external to the system - config files, etc. - so you need something that gets the information from somewhere and instantiates the correct class - and trust me, you don't want to write Protocol proto = null; if(config == "protocolA") proto = new ProtocolA; else if(config == "protocolB") proto = new ProtocolB; else if(config == "protocolC") proto = new ProtocolC; else if(config == "protocolD") proto = new ProtocolD; else throw whatever; return new MyObjectWithDependencies(proto); especially when your system supports >50 protocols, and your object also needs a logger which can itself be of 12 different kinds, a file accessor which can mmap or not according to configuration & os, etc etc
- HereBeBeasties 7y ago> The reason why we have DI and DI frameworks is because we are asked in requirements to make things configurable out-of-code (and at runtime) That's a reason, but it's far from the only one. The way I've seen DI used over the years is far more about separating out concerns in the code via interfaces, or making things testable without side effects, than it is making those things dynamically pluggable / controllable via config, not code. The majority of interfaces passed as dependencies into constructors have a single real implementation (outside of unit tests). I lately err on the side of explicit manual wiring as the cost saving of doing it all automatically does not usually offset the costs of extra magic and lack of compile-time safety that it incurs. Exceptions are where there is a lot of AoP interceptor stuff to wire in, or if I want something to help with lifecycle scoping (e.g. per-request lifetime for a set of related things), at which point a DI framework will likely start paying for itself.
- mrec 7y agoI generally share your view, and have never really understood the appeal of the magic woo frameworks. I asked an interview candidate about this once (he'd spoken positively about them) and he very honestly said that yep, it's all about bypassing change control restrictions. Which is a pragmatic reason, but not a good one at the organizational level. It's every bit as easy to break your system via a config change as via a code change.
- UK-Al05 7y agoI don't how a IoC container would allow you bypass change control? Because config is not covered by change control in your case?
- mrec 7y agoTheir case, not mine, but yes, I gathered that change control could be skipped for "config-only" changes. Don't ask me why, it sounded crazy to me too.
- mywittyname 7y ago
- aikah 7y ago> That is so weird. The reason why we have DI and DI frameworks is because we are asked in requirements to make things configurable out-of-code (and at runtime), because someone wants to use a pretty UI or a config file of sorts to set up which behaviour is used to do $thing. Which is ironic in regard of DI frameworks that rely on in-code annotations to wire dependencies, especially in compiled languages. Let's not even get started with languages that do not allow ad-hoc object/value creation from external manifests directly, like Go.
- 0x445442 7y agoYeah I've been working with a lot of AWS lambdas the past year and one of the design decisions was to limit our jar sizes because of warm up time concerns. So, libs like Spring or Guice are not allowed and I can say we really haven't missed them as we just construct new objects by passing in their dependencies when needed.
- thrower123 7y agoYes, this is a good way to ensure that you aren't doing horrible, horrible things inadvertently. When you can magic up a dependency from a service locator or DI container, you don't have to think as much about what you are actually doing. Having to look at a constructor with seventeen parameters passed in highlights that you've made a mess of your design.