From: Trans Date: 2007-06-14T19:04:29+09:00 Subject: Re: Disadvantages of Dependency Inversion? On Jun 8, 10:47 pm, Daniel DeLorme wrote: > I think the best article on the topic is this by Martin Fowler:http://www.martinfowler.com/articles/injection.html > He does a good job of analyzing the pros and cons. And basically I agree > with him; DI is useless unless you write 3rd party packages. For a long time I felt DI was very interesting and potentially very useful, but I never could quite get mileage out of it. I think I finally figured out why: DI is just a contrived codification of an essentially simple top-level construction layer. Here's what I mean. Reading Jim's http://onestepback.org/articles/depinj/, he gives this basic example: magic_lamp = DIM::Container.new magic_lamp.register(:warmer) { |c| Warmer.new(c.pot_sensor, c.heater) } magic_lamp.register(:pot_sensor) { |c| PotSensor.new(c.pot_sensor_io_port) } magic_lamp.register(:heater) { |c| Heater.new(c.heater_io_port) } # Hardware IO Port Assignments magic_lamp.register(:pot_sensor_io_port) { 0x08F0 } magic_lamp.register(:heater_io_port) { 0x08F1 } magic_lamp.register(:coffee_maker) { |c| MarkIV::CoffeeMaker.new(c.boiler, c.warmer) } coffee_maker = magic_lamp.coffee_maker The magic of the lamp seems quite wonderful, granting us the flexibility of indirection in lew of a little complexity. And though Jim goes on to tell us that DI isn't so important for Ruby because we can dynamically define constants instead (eg. Heater = Mocking::Heater), I think that's missing the point a bit. Somewhere along the line the constants must be "injected" too. No, the real lack luster of the genie's lamp comes from a slight of hand, because no magic is actually required. class JustALamp def warmer Warmer.new(pot_sensor, heater) end def pot_sensor PotSensor.new(pot_sensor_io_port) end def heater Heater.new(heater_io_port) end # Hardware IO Port Assignments def pot_sensor_io_port 0x08F0 end def heater_io_port 0x08F1 end def coffee_maker MarkIV::CoffeeMaker.new(boiler, warmer) end def self.coffee_maker new.coffee_maker end end coffee_maker = JustALamp.coffee_maker So it seems to me that the heart of DI is really nothing more than a good programming practice --using an control layer. Of course, I'm no DI expert, so maybe I'm missing something. But this certainly helps to explain why all this magic never seemed to pane out for me in practice. (BTW, a nice side-effect of this simplification, JustALamp can be easily subclassed.) T.