Dependency Inversion Principle in Ruby
I knew that the rule existed but I couldn’t imagine it properly. I wasn’t able to understand “inversion” with codes. That’s why I actually wrote codes about DIP in order to make easier to comprehend it. The codes are quoted from “practical object-oriented design in ruby”.
sample codes
# wheel class depends on gear classclass Gear
attr_reader :chainring, :cog
def initialize(chainring, cog)
@chainring = chainring
@cog = cog
end def gear_inches(diameter)
ratio * diameter
end def ratio
chainring / cog.to_f
end
endclass Wheel
attr_reader :rim, :tire, :gear
def initialize(rim, tire, chainring, cog)
@rim = rim
@tire = tire
@gear = Gear.new(chainring, cog)
end def diameter
rim + (tire * 2)
end def gear_inches
gear.gear_inches(diameter)
end
endp Wheel.new(26, 1.5, 52, 11).gear_inches
It is clear that the method in Gear Class is called in Wheel Class. In other words, if Gear Class changes, Wheel class will be affected. Therefore, Wheel Class depends on Gear Class.
On the other hand,
# gear class depends on wheel classclass Gear
attr_reader :chainring, :cog, :wheel
def initialize(chainring, cog, wheel)
@chainring = chainring
@cog = cog
@wheel = wheel
end def gear_inches
ratio * wheel.diameter
end def ratio
chainring / cog.to_f
end
endclass Wheel
attr_reader :rim, :tire
def initialize(rim, tire)
@rim = rim
@tire = tire
end def diameter
@rim + (@tire * 2)
end
endp Gear.new(52, 11, Wheel.new(26, 1.5)).gear_inches
in this case, the method of Wheel Class is called in Gear Class. The result will be opposite.
How can we realize DIP?
In the case of the codes above, it is important to decide which class should have gear_inches method and which instance should be injected. If we think that wheel class is rarely changed, we should inject wheel class into gear class. The key to comprehend DIP is to understand which class refers to which instance.