On Jun 8, 10:47 pm, Daniel DeLorme [email protected] wrote:
I think the best article on the topic is this by Martin F.:Inversion of Control Containers and the Dependency Injection pattern
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 OSCON 2005 - Dependency Injection - Cover, 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.