From: Jamis Buck Date: 2004-10-12T00:48:05+09:00 Subject: Re: DI service change notifications (Syringe) Eivind Eklund wrote: > On Mon, 11 Oct 2004 09:12:47 +0900, Jamis Buck wrote: > >>I guess what I'm feeling is that there is no general way to know, >>definitively, all of the dependencies of a service, especially in a >>dynamic language like Ruby. Without putting restrictions on when and how >>services are defined (like Copland does), I'm not sure how to come up >>with a general solution to this. > > > I get a feeling you're overengineering here. > > Doesn't something like the following work? > > class Registry > def initialize > @registry = Hash.new > @active_dependency_registrations = [] > @dependencies = Hash.new > end > # This is done by method_missing in Syringe > def get(symbol) > register_dependency(symbol) > retval = nil > begin > start_dependency(symbol) > @registery[symbol].call > finally > end_dependency(symbol) > end > end > def register(symbol, &block) > @registery[symbol] = block > end > def start_dependency(symbol) > if (@active_dependencies.include? symbol) > raise "Circular dependency" > else > @active_dependencies.each do |dependent_symbol| > @dependencies[dependent_symbol] ||= [] > @dependencies[dependent_symbol] |= [symbol] > end > @active_dependencies |= [symbol] > end > end > def end_dependency(symbol) > @active_dependencies -= [symbol] > end > end > My head hurts. :) > It builds a dependency tree only inside the present registry. Fascinating approach, Eivind. Let me see if I read this right. * Registering the callback is nothing special -- just storing the callback in the hash. * When a service is requesed, you register the requested service as a dependency of whatever service is currently being constructed. > > It only count the directly called methods from call/yield, but that > should be OK for most cases. Indeed. However, if this kind of functionality were to be put into the core of the framework, I would personally prefer to see it robust enough to either capture all dependencies, regardless of where or how they are created, or none of them. Given Syringe's current implementation, I don't think an efficient, general-purpose solution meeting that criterion can be devised. I'd love to be proven wrong, though. :) (On a related note: I just registered a RubyForge project under the name "Needle". I think "Needle" is easier to say, spell, and remember, and still captures what "Syringe" was trying to imply, as well. In future posts, I'll be referring to 'Syringe' as 'Needle', since Syringe was just a code-name anyway.) -- Jamis Buck jgb3@email.byu.edu http://www.jamisbuck.org/jamis