Composition over Inheritance
with Ruby
Inheritance
According to Wikipedia:
"A way to reuse code of existing objects, or to establish a subtype from an existing object, or both"
Composition
According to Wikipedia:
"A technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance."
Let's code
class Song
ANIMALS = [:pava, :gata, :chiva, :mona, :lora, :perra, :burra]
def initialize
@data_song = {}
ANIMALS.each do |animal|
mother = animal.to_s
child = mother[0..-2] + "ito"
@data_song[animal] = ["compré una #{mother}, y la #{mother} tuvo un #{child}",
"Tengo la #{mother}, tengo el #{child}"]
end
end
def animals
ANIMALS
end
def recite
line(ANIMALS.count)
end
def line(number)
"Con real y medio #{phrase(number).join(' ')} y siempre tengo mi real y medio "
end
def phrase(number)
animals.first(number).reverse.map.with_index do |animal, index|
index == 0 ? @data_song[animal].join(' ') : @data_song[animal][1]
end
end
end
Our base class
Base class
1st Feature
RandomSong
without if statements
Inheritance!!!!
class RandomSong < Song
def animals
super.shuffle
end
end
RandomSong
RandomSong
2nd Feature
EchoSong
without if statements
Inheritance!!!!
Yes... Again!!
EchoSong
class EchoSong < Song
def phrase(number)
super.zip(super).flatten
end
end
EchoSong
Last Minute Feature
EchoSong + RandomSong
EchoRandomSong
Inheritance??
class Song
#Crappy Code
end
class RandomSong < Song
def animals
super.shuffle
end
end
class EchoRandomSong < RandomSong
def phrase(number)
super.zip(super).flatten
end
end
EchoSong + RandomSong
class Song
#Crappy Code
end
class EchoSong < Song
def phrase(number)
super.zip(super).flatten
end
end
class EchoRandomSong < EchoSong
def animals
super.shuffle
end
end
EchoSong + RandomSong
Make a new Subclass with all the code!!!!!
class Song
#Crappy Code
end
class EchoRandomSong < Song
def phrase(number)
super.zip(super).flatten
end
def animals
super.shuffle
end
end
EchoSong + RandomSong
Duplicate all the code???
Really?
NO!!
WWSMD
Composition!!
Analize the subclasses
RandomSong "is-a" Song?
EchoSong "is-a" Song?
RandomSong is just a role
Orderer role
EchoSong is a role too
Formatter role
Extract the roles and convert them in dependencies
class DefaultOrder
def order(data)
data
end
end
class RandomOrder
def order(data)
data.shuffle
end
end
class Song
ANIMALS = [:pava, :gata, :chiva, :mona, :lora, :perra, :burra]
def initialize(orderer: DefaultOrder.new )
@data_song = {}
@animals = orderer.order(ANIMALS)
@animals.each do |animal|
mother = animal.to_s
child = mother[0..-2] + "ito"
@data_song[animal] = ["compré una #{mother}, y la #{mother} tuvo un #{child}",
"Tengo la #{mother}, tengo el #{child}"]
end
end
def recite
line(@animals.count)
end
def line(number)
"Con real y medio #{phrase(number).join(' ')} y siempre tengo mi real y medio "
end
def phrase(number)
@animals.first(number).reverse.map.with_index do |animal, index|
index == 0 ? @data_song[animal].join(' ') : @data_song[animal][1]
end
end
end
class EchoFormatter
def format(phrases)
phrases.zip(phrases).flatten
end
end
class DefaultFormatter
def format(phrases)
phrases
end
end
class Song
ANIMALS = [:pava, :gata, :chiva, :mona, :lora, :perra, :burra]
def initialize(orderer: DefaultOrder.new, formatter: DefaultFormatter.new)
@data_song = {}
@animals = orderer.order(ANIMALS)
@animals.each do |animal|
mother = animal.to_s
child = mother[0..-2] + "ito"
@data_song[animal] = ["compré una #{mother}, y la #{mother} tuvo un #{child}",
"Tengo la #{mother}, tengo el #{child}"]
end
@formatter = formatter
end
def recite
line(@animals.count)
end
def line(number)
song = @formatter.format(phrase(number))
"Con real y medio #{song.join(' ')} y siempre tengo mi real y medio "
end
def phrase(number)
@animals.first(number).reverse.map.with_index do |animal, index|
index == 0 ? @data_song[animal].join(' ') : @data_song[animal][1]
end
end
end
Composition
-
Isolate the thing that varies
-
Name the concept
-
Define the role
-
Inject the player
Inheritance
is for specialization
not for sharing code
Gustavo Giménez
@gonzo_
@gusga
Composition over inheritance
By Gustavo Giménez
Composition over inheritance
Composition over Inheritance presentation based/inspired in Sandy Metz conf
- 341