9 ms·
The benefit of a dependency injection framework is that you don't have to figure out the order of the dependency tree. If you do this work manually, then you h
by eeperson 7y ago
The benefit of a dependency injection framework is that you don't have to figure out the order of the dependency tree. If you do this work manually, then you have to make sure to instantiate things in a particular order so that dependencies are initialized before the classes that depend on them. This can be big pain if you have a large number of classes and start refactoring things.
I can understand some hesitation about using a dependency injection framework. Some of them can be very hard to reason about (especially the run time frameworks). However, they don't have to be that hard to reason about. My personal favorite is a compile time dependency injection framework for scala called Macwire[1]. In scala, you might do manual dependency injection like this:
val instantiated = new Class(dependency1, dependency2)
With Macwire you could write the same thing as:
val instantiated = wire[Class]
The wire macro above, automatically looks up dependencies by type and creates an instance of Class with those dependencies as arguments. If you combine that macro with Scala's built in support for laziness then you don't have to worry about initialization order either. This gives you something that is fairly easy to reason about (it is basically what your were doing by hand before) and will sort our necessary dependencies for you (and error out of they are missing).
[1] https://github.com/adamw/macwire https://github.com/adamw/macwire
- sagichmal 7y ago> The benefit of a dependency injection framework is that you don't have to figure out the order of the dependency tree. What! This is essential knowledge. Without it, how can you possibly build a coherent mental model of a program?! I’ve never heard this justification before, it’s bonkers.
- jimmyspice 7y agoPretty reasonable to me. maybe that exposes how relatively junior I am (I'm not OP) but the codebase I use is sufficiently large that if I tried to handwrite the dep tree before I started working, I wouldn't have gotten any work done at all.
- sagichmal 7y agoWild. I can’t do any meaningful work on a codebase until I’ve mapped out the component graph.
- eeperson 7y agoSorry, perhaps I should have been a little clearer. What I meant is that you don't need to figure out the order in which you have to construct the dependency tree. The order of the tree itself (as in what depends on what) is something you still need to specify and should know. EDIT - You have a tree of dependencies. This is something you care about. In order to create that tree in code, you have to convert it to a linear series of statements. This conversion is something you don't really care about as long as you end up with the tree you want. Dependency injection frameworks should make it so you can declaratively specify that tree without having to worry about how it is actually constructed.
- sagichmal 7y agoThis doesn't really make sense to me. The dep graph is a second-order thing, a conceptual model that's emergent from the parameters to the imperative constructors. It's not a first-order thing that we manipulate directly. There's no way to even represent a graph in a text file without flattening it to some order, anyway. The point being made is that just writing the construction statements in the main method is exactly "declaratively specify[ing] that tree", and that "having to worry about how it is actually constructed" is incredibly valuable knowledge to maintainers, because it allows them to see explicitly how components are constructed, and how they interact with each other. It's not something you want to hide with a framework, it's something you want to lift up, front-and-center, so everyone can see it.