5 ms·
sigh DI is not the same as an IOC container. Get it right ffs, if you want people to take you seriously. DI: class Blah(): def __init__(self, depen
by shadowmint 13y ago
sigh
DI is not the same as an IOC container. Get it right ffs, if you want people to take you seriously.
DI:
class Blah():
def __init__(self, dependency):
self.dep = depedency
IOC:
my_blah = container.resolve(Blah)
Anyway, onto my main complaint:
"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."
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?
Intuitive.
Also, what's wrong with annotations? I'm rather fond of this sort of 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()
Or in pinject:
obj_graph = pinject.new_object_graph(binding_specs=[SomeBindingSpec()])
needs_provider = obj_graph.provide(NeedsProvider)
But wait, I want a test. Ok~
instance = UsesType(my_mock)
Or in pinject:
??????
In fact, pinject doesn't even mention tests in its documentation. Whew~ That's only the whole reason for using DI in the first place.
Self important library is self important. Not amazed.
- nbevans 13y ago"IOC: my_blah = container.resolve(Blah)" That's not IOC. That's service location. Which is only used at the "composition root" (look it up) in IOC. "In fact, pinject doesn't even mention tests in its documentation. Whew~ That's only the whole reason for using DI in the first place." No, testing accounts for just one of the more minor reasons to be using DI.
- shadowmint 13y agoI would argue the single greatest benefit (possibly, only benefit) that DI provides over other service location options (eg. factories) is that you get a nice means to test independent units of code by providing mock implementations. In dynamic languages with no real 'private' members, the benefit is actually pretty minimal because you can assign mock service instances after the object is created. eg. test_instance = Blah() test_instance.service = MockService() vs. test_instance = Blah(MockService()) ...which means, there isn't a lot of point in using it, unless you're using an IOC container which gives you some other synergy bonuses like singletons, per thread and per request instances, configuration file driven implementation binding, etc.
- nbevans 13y agoNo the single greatest benefit that a IOC container provides is object lifetime and scoping management. The next greatest benefit is the ability to decompose your code base into a single responsibility adhering components with good decoupling and namespace cohesion characteristics. Testing is very low down on the list of advantages of a IOC container. And even then, most people that think they're doing testing properly with a IOC container are doing it wrong. Hint: "Re-binding" your container by forcing it to drop an existing service implementation and replacing it with your mock/test implementation is "doing it wrong". The reason there is always so much discourse around DI and IOC is because very few programmers actually bothered to learn, and grok it, even if they think they already have.
- _pmf_ 13y agoI agree. Testing with heavily mocked implementations is basically useless. Especially under time pressure, I tend to focus more on system and integration tests than on cute unit tests that tend to find issues that never occur in practice and don't find issues that occur when the first user has his first minutes with the system. "Hooray, my setName sets the name correctly!" - well, my congratulations.
- dragonwriter 13y ago> Testing is very low down on the list of advantages of a IOC container. And even then, most people that think they're doing testing properly with a IOC container are doing it wrong. Hint: "Re-binding" your container by forcing it to drop an existing service implementation and replacing it with your mock/test implementation is "doing it wrong". What part of that is wrong? I may be missing your focus, but that sounds right for unit testing.
- nbevans 13y agoIt's wrong because your unit tests, just like your application, should not be aware of the presence of an IoC container except at the absolute composition root. Your unit test libraries should have their own composition roots of their own and it is at this level, in configuring the IoC "modules" (as they are often called) that special mock services would be provided. If your test cases are littered with crap concerning your IoC container, re-binding stuff, then something is badly wrong. Sadly, pretty much all projects I've seen that use IoC end up writing their tests in this way. Someone wasn't thinking. Your tests should be treated with the same adherence to SOLID principles as your application code. They are first class citizens of your code base. So why dirty your tests by having them coupled to your IoC container?
- pekk 13y agoLess documentation is better? That's not something I hear every day.