Check out Stuart Sierra's "component" for another take. Of course, another take is that you're better off just constructing objects by calling their constructors directly.
After using Clojure for a while, i've found that some of the ideas from OO still apply to larger systems. It just happens that most programs, because of the functional programming style, dynamic typing, and Clojure's abstractions, end up too small / simple to warrant introducing them into the codebase.
Well, "dependency injection" is a pompous term. This just relies on two simple clojure features: protocols and namespace introspection to easily configure a program. It's definitely not a framework, but I see how using the term DI can be a bit scary and off-putting.
I'd like to think it's common for programs to need extensions & plugins, without it deriving from "the point of of clojure".
DI isn't scary sounding, it's just unnecessary most of the time I've seen it, especially in public facing APIs that third party developers use. Most classes don't have so many varied amounts of diverse dependencies where you have to resort to convoluting the constructors for the sake of testing. You could just use inheritance.
Dependency injection takes a thing that should be one line of code and makes it twenty lines. It requires third party developers to have know all kinds of unnecessary implementation details. DI is a piece of shit that should be a measure of last resort and if you find yourself resorting to it often maybe question your entire architecture.
I have yet to meet one person to convince me that DI is not unnecessary in most cases. It always boils down to making writing tests easier. Well you should not shit all over your public APIs for the sake of testing.
That's exactly what I was thinking. I've not used Clojure specifically, but in the sitations where OO people use dependency injection I tend to use a free monad with multiple interpreters. I'm yet to make serious use of an algebraic effect system, but that would make this even simpler and more composable.
The one-function protocols strike me as unidiomatic; why not use functions directly? `(fn […] …)` would work just as well as `(reify P (f [this …] …))` (`this` is never used).
Update: I looked at the code again and noticed that `stdin-transport` implements two protocols. Guess I need to think a little bit more about this.
A chapter from the O'Reilly book covers this subject pretty well. With Clojure's java interop, you can still use Spring. Thanks to the homoiconicity of the language, support for higher order functions, and with some clever use of Clojure's load-file function in core, you kind of get DI baked into the language for free.
12 comments
[ 3.5 ms ] story [ 15.3 ms ] threadI'd like to think it's common for programs to need extensions & plugins, without it deriving from "the point of of clojure".
Dependency injection takes a thing that should be one line of code and makes it twenty lines. It requires third party developers to have know all kinds of unnecessary implementation details. DI is a piece of shit that should be a measure of last resort and if you find yourself resorting to it often maybe question your entire architecture.
I have yet to meet one person to convince me that DI is not unnecessary in most cases. It always boils down to making writing tests easier. Well you should not shit all over your public APIs for the sake of testing.
It's just a rather a simple mechanism to provide an extension mechanism for a daemon.
Update: I looked at the code again and noticed that `stdin-transport` implements two protocols. Guess I need to think a little bit more about this.