[kforge-dev] Dependency Injection in Domain Model, Kforge

Rufus Pollock rufus.pollock at okfn.org
Sun May 20 12:13:04 UTC 2007


John Bywater wrote:
> [Posted on behalf of David Heath; his attempt bounced.]

David, sorry to hear your messages are getting bounced. I'm looking into 
this following John's suggestions and hope it will get fixed soon.

> Dear All,
> 
> I've recently started some work with John to make piece of software
> caleld "eternity", for helping to run fixed time-box projects. In the 
> process
> of this, I started working with the Domain Model library, and noticed a
> problem with the current dependency injection system in use.
> 
> The current library, which was taken from:
>    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413268
> 
> has code which looks a bit like this (example from dm.plugin.base):
> 
>     from dm.ioc import *
> 
>     class PluginBase(object):
>         logger = RequiredFeature('Logger')
> 
> The calls to RequiredFeature within services, together with the widespread
> import of dm.ioc, exhibit the "container dependency" anti-pattern:
> 
>     http://www.picocontainer.org/Container+Dependency
> 
> This is a problem because it eliminates some of the main benefits of
> dependency injection, namely:
> 
>     i) container agnosticism: with container dependency, components 
> expect a
> particular type of container to be in use. Components can't be used in 
> other
> containers, or on their own. If container dependency is eliminated,
> components could be used stand-alone or in other frameworks and containers
> with no problem
>     ii) testability: with container dependency, you have to use and 
> configure
> a particular container in order to test. In the DM case, the container is
> just a global variable, and so it's hard to avoid interference between one
> set of tests and another. Without the container dependency, you can unit 
> test
> each component in isolation, and don't need to use a container. The
> dependencies can be explicitly satisfied in the tests, e.g. by providing 
> mock
> objects.

These are both excellent points.

> After a bit of research, and seeing the elegant approach which had been 
> taken
> in ruby [1], I decided to see if I could find a simple, easy to use,
> non-intrusive way to make dependency injection work for the domain
> model/kforge code. To this end I implemented a simple dependency injection
> container which I've called "DIPPY" (for Dependency Injection in 
> PYthon). The
> source code can be downloaded here:
> 
> http://project.kforge.appropriatesoftware.net:9080/eternity/svn/trunk/src/ete 
> 
> rnity/
> 
> The code is in dippy.py. There are also full unit tests in dippy_test.py 
> plus
> a simple example in dippy_example.py.
> 
> About DIPPY:
> 
> My aim with DIPPY was to make a very simple container supporting primarily
> constructor injection and also setter injection, which would support the
> current code of DM without requiring it to be modified too much. The Pico
> Container folks make point out some strong benefits of constructor 
> injection
> over setter injection [2], but setter injection can be less intrusive 
> and is
> more similar to the current implementation using RequiredFeature().

This sounds great. I would entirely support this module being added into 
the dm package.

> Migrating to constructor injection would require some simple refactoring of
> the domain model code. The final result would be an easier to test system,
> with more explicit dependency relationships, and obviously no longer
> suffering from the container dependency anti-pattern. Migration could be 
> done
> in a piecemeal fashion, whilst keeping all tests running.

I particularly support this :) Let's keep the system functional at all 
times.

> Other python frameworks:
> 
> I've also just realised that my initial research wasn't thorough enough and
> that there are actually two other dependency injection frameworks for 
> Python:
> PyContainer and Aglyph. Of the two, Aglyph seems to be under more active
> development and also has unit tests wheras PyContainer does not. They both
> provide facilities for doing component wiring using XML files (which I 
> don't
> really think is that useful), and Aglyph also allows component wiring in
> plain python (not sure about PyContainer).
> 
> Questions:
> 
> Sorry for the long email, and thanks for making it this far. I'd love to 
> hear
> your input and thoughts on this. Do you have any experience with any of the
> other python DI frameworks? What do you think of DIPPY? Do you think it 

John was the man who wrote the original ioc code so he is probably the 
better person to comment here.

> would
> be good to refactor DM to us constructor injection or is it just fine 
> how it
> is?

Having read your mail and the linked references I think your suggestion 
for a modification makes a great deal of sense. Of course John is more 
knowledgeable in this area than I would defer to him to have the final 
word on this but my feeling is that this is a refactoring/improvement 
that should be done.

Regards,

Rufus




More information about the kforge-dev mailing list