Brian Candler wrote:
> I was completely unaware of DI/IoC until now, so hopefully I'm a good
> candidate :-) I'd say it's an excellent document.
> 
> I immediately recognised the Service Locator pattern, which I've been using
> without knowing it as such. To build the webapp that you describe, rather
> than building the construction knowledge into Webapp.initialize, I would
> build an outer skeleton 'runner' which instantiates all the objects and
> links them together:
[... code elided ...]

Interesting.  You are effectively creating a separate service locater 
for each component.  As you demonstrate, there are an infinite number of 
variations in these patterns.

> In practice, there tends to be multiple versions of the skeleton. I might
> have one version which runs under fastcgi, and another which starts a
> webrick server, for example. Or I might decide to put the one of the objects
> on a different machine, and access it via DRB. So the main problem I have is
> that I end up with lots of very similar skeletons for different uses (unit
> testing, command-line runner, fastcgi, webrick etc), so if the plumbing
> needs to change, I have to remember to change each of the skeletons
> accordingly.
> 
> DI would still require this plumbing, so I'm not sure it helps with this
> particular problem, except perhaps I could put some of the invariant parts
> of the DI skeleton into a library.

One of the variations I discussed with Jamis included the possibility of 
layering DI containers with namespaces.  If I understand the concept 
correctly, you configure the base system in a root namespace and then 
layer the variations in namespaces on top of the root.  If a service 
isn't located in the specific namespace for the (lets say) Fast CGI 
version, then it uses the services configured in the root.  This would 
reduced the duplication in the system.

Another approach is to use a single DI container, but configure it with 
in different methods.  One method could populate the static portion of 
the application,  and then different methods could populate it according 
to whether it was a Fast CGI configuration or a webrick configuration.

> So the main advantages I can see for the DI approach are:
> 1. When object creation must be dynamic, i.e. you can't pre-plumb
>    everything [I presume you could pass the DI object into the application,
>    and let it create things on demand later];

That's one approach.  It does tie your system into a particular DI 
framework at that point.  If you want it to remain independent, then 
just configure the DI container with a factory for the dynamic object 
creation.

For example, once I built a system that could generate events in our 
middleware product.  All I needed to do was register the class of the 
events that I wanted to create, eg.

   container.register(:event_class) { MiddlewareEvent }

And then later, use that class to create the events.

   event_creator = container.event_class
   ...
   event_creator.new

This should also work with a service locater approach as well.

> Finally, one thing I don't understand. In your final example, using DI in
> your method "def create_application", I see all the dependencies registered
> but not actually something which say "create me an :app and run it".  [...]

Hmmm ... I was so concerned about getting the little pieces right I 
missed the big one.  That function probably should have ended by 
returning:   container.app

-- 
-- Jim Weirich    jim / weirichhouse.org     http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)