Since I have touched on the principles of SOLID, I think it is worth spending a chapter addressing them fully. SOLID is an acronym representing five principles that go in to making high quality, maintainable software.
A class should only have one responsibility.
Classes should be open for extension, but closed for modification.
Any object should be replacable by an instance of their subclasses without affecting the correctness of the program.
A client should not be forced to implement an interface that it doesn't use.
Depend on abstractions, not on concretions. This is a simple affair in Ruby thanks to its dynamic typing, and can be achieved simply by applying a few techniques.
Look at the following example.
class Hamster
def feed
do_something_with(HamsterFood.new)
end
end
In this case, Hamster
depends on HamsterFood
. If HamsterFood
changes, we may have to change Hamster
. If want to feed Hamster
something other than HamsterFood
, we definitely have to change Hamster
. We can avoid this conundrum by injecting our dependencies.
class Hamster
def feed(food)
do_something_with(food)
end
end
Hamster
no longer depends on the concrete. It relies on the programmer to supply an object that can be treated like HamsterFood
. Perhaps any subclass of Food
!
hamster = Hamster.new
[Hamburger, Tomato, Cheese, Spaghetti, Burrito].each do |foodstuff|
hamster.feed(foodstuff.new)
end
That's one full hamster. More importantly, it's a hamster that doesn't have to change no matter what we want to feed it, so long as that food obeys some basic rules about what it entails to be Food
.