I don't get dependency injection. I come from languages that I am told don't have it. But when I read the Wikipedia page for DI, I get:<p>"a dependent consumer<p>a declaration of a component's dependencies, defined as interface contracts<p>an injector (sometimes referred to as a provider or container) that creates instances of classes that implement a given dependency interface on request."<p>Wait, I still have to declare dependencies, just like the import statement in python, require.js in JS, etc. which are apparently not 'dependency injection' systems? And this just adds, er more code?<p>That same wikipedia page mentions dynamically loaded dependencies while also mentioning 'a declaration of a components dependencies' which sure doesn't sound dynamic to me.<p>Does anyone care to provide a better explanation of what dependency injection gives me over the existing common dependency mechanisms?
<i>sigh</i><p>DI is not the same as an IOC container. Get it right ffs, if you want people to take you seriously.<p>DI:<p><pre><code> class Blah():
def __init__(self, dependency):
self.dep = depedency
</code></pre>
IOC:<p><pre><code> my_blah = container.resolve(Blah)
</code></pre>
Anyway, onto my main complaint:<p><pre><code> "Pinject is a pythonic dependency injection library. Python ports of other libraries, like
Spring or Guice, retain the feel (and verbosity) of being designed for a statically typed
language. Pinject was designed from the ground up for python."
</code></pre>
Wow, I'm impressed. Designed from the ground up for python. That's why you needed ~20 pages of documentation on how to use it?<p>Intuitive.<p>Also, what's wrong with annotations? I'm rather fond of this sort of code:<p><pre><code> ### implements, resolve, Scope
class IType(object):
prop1 = None
def call(self):
pass
@implements(IType)
class ImplType(object):
prop1 = "Value"
def call(self):
pass
scope = Scope()
scope.register(ImplType)
@resolve(scope)
class UsesType(object):
def __init__(self, t=IType):
self.t = t
instance = UsesType()
</code></pre>
Or in pinject:<p><pre><code> obj_graph = pinject.new_object_graph(binding_specs=[SomeBindingSpec()])
needs_provider = obj_graph.provide(NeedsProvider)
</code></pre>
But wait, I want a test. Ok~<p><pre><code> instance = UsesType(my_mock)
</code></pre>
Or in pinject:<p><pre><code> ??????
</code></pre>
In fact, pinject doesn't even mention tests in its documentation. Whew~ That's only <i>the whole reason for using DI in the first place</i>.<p>Self important library is self important. Not amazed.
The author could refactor the documentation a little, starting with removal of the word "Pythonic" and perhaps ending only after 90% of the text has been replaced with a single section entitled "WHY GOD WHYYYYY".<p><pre><code> def python_di_copyright_2069_hosay123(dep, *args, **kwargs):
modname, _, classname = dep.rpartition('.')
mod = importlib.import_module(modname)
return getattr(mod, classname)(*args, **kwargs)
</code></pre>
> Though Google owns this project's copyright, this project is not an official Google product.<p>We just published it under Google's Github to give a terrible project implied legitimacy that it likely doesn't even have internally.
I understand dependency injection, but I never understood dependency injection frameworks. For me the whole point of DI is explicit composability.
There should only be a few well defined places in my application where all my classes are assembled into a working program. If my classes cover my domain nicely, I should be able to compose all kinds of programs (including tests) and reuse code.<p>If my objects get injected to each other automatically by their name then my dependencies are just as predetermined, which results in coupled code, except the coupling is now difficult to read or modify.<p>Once I decided I am only using explicit injection, I don't need a framework, I just instantiate my classes in the right order and pass them into each other. What can possibly be more pythonic than that?<p>I have the same issue with Angular.js btw. They are trying to make is easy to start by adding dependency injection magic, but in reality all I see is "this can't possibly work (and indeed it doesn't)", so I just need to spend more time digging and understanding the magic before I can start writing ANY code.<p>Every documentation should start by explaining the explicit way of doing things, then adding the sugar afterwards.<p>import this
Dependency Injection (DI) and Dependency Injection Containers (DIC) are the "in-thing" in PHP at present, and to speak against them [0] is - like disagreeing with anything fanboys latch onto - ridiculed, without a sensible discussion or explanation.<p>From a testing perspective I sort-of get it; from a "this is less tightly coupled" I don't: all you've done is move the coupling to a different level. Code always has to be coupled at some level, so where's the advantage?<p>With the amount of noise about DI I'm sure it's something I should pay attention to rather than be turned off (as happened with Rails), but I really don't et it. Can anyone provide the missing piece in my thinking?<p>[0] <a href="http://till.klampaeckel.de/blog/archives/154-Dependency-Injection-Containers.html" rel="nofollow">http://till.klampaeckel.de/blog/archives/154-Dependency-Inje...</a>
Implicit class bindings sound like a really bad idea and hard to debug.<p><pre><code> Pinject creates implicit bindings for classes.
The implicit bindings assume your code follows PEP8
conventions: your classes are named in CamelCase, and
your args are named in lower_with_underscores. Pinject
transforms class names to injectable arg names by
lowercasing words and connecting them with underscores.
It will also ignore any leading underscore on the class
name.
If two classes map to the same arg name, whether those
classes are in the same module or different modules,
Pinject will not create an implicit binding for that arg
name (though it will not raise an error).</code></pre>
that looks pretty good.<p>not sure if i overlooked it in the notes or not, but i have a couple questions.<p>you mentioned copyright at the end. what sort of license are you releasing it under?<p>Does it support nested creation of objects? ( ie if you ask for an instance of class 'FOO' and FOO has a DI or 'BAR' will BAR be first created and then injected into FOO)