Created
March 25, 2015 23:44
-
-
Save kchens/c190e745ab14ef29598d to your computer and use it in GitHub Desktop.
POODR: Chapter 5 - Reducing Costs With Duck Typing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# Overlooking Ducks | |
# 1 -------------------BAD | |
class Trip | |
attr_reader :bicycles, :customers, :vehicle | |
def prepare(mechanic) | |
# no depedency on mecahnic | |
# create a dependency that the object must respond to #prepare_bicycles | |
mechanic.prepare_bicycles(bicycles) | |
end | |
# ... | |
end | |
class Mechanic | |
def prepare_bicycles(bicycles) | |
bicycles.each { |bicycle| prepare_bicycle(bicycle) } | |
end | |
def prepare_bicycle(bicycle) | |
# ... | |
end | |
end | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# Compounding The Problem | |
# 2 -------------------WORST | |
class Trip | |
attr_reader :bicycles, :customers, :vehicle | |
def prepare(preparers) | |
# Method now needs to check each object for its class | |
# In scaling an app, this case statement grows | |
preparers.each do | preparer | | |
case preparer | |
when Mechanic | |
preparer.prepare_bicycles(bicycle) | |
when TripCoordinator | |
prepare.buy_food(customers) | |
when Driver | |
prepare.gas_up(vehicle) | |
prepare.fill_water_tank(vehicle) | |
end | |
end | |
end | |
end | |
class TripCoordinator | |
def buy_food(customers) | |
# ... | |
end | |
end | |
class Driver | |
def gas_up(vehicle) | |
# ... | |
end | |
def fill_water_tank(vehicle) | |
# ... | |
end | |
end | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# Finding the Duck | |
# 3 -------------------BEST | |
class Trip | |
attr_reader :bicycles, :customers, :vehicle | |
# prepare ultimately has a single purpose, its arguments arrive wishing to | |
# collaborate to accomplish a single goal. | |
def prepare(preparers) | |
# passes self as a parameter | |
preparers.each { |preparer| preparer.prepare_trip(self) } | |
end | |
end | |
class Mechanic | |
def prepare_trip(trip) | |
trip.bicycles.each { |bicycle| prepare_bicycle(bicycle) } | |
end | |
# ... | |
end | |
class TripCoordinator | |
def prepare_trip(trip) | |
buy_food(trip.customers) | |
end | |
# ... | |
end | |
class Driver | |
def prepare_trip(trip) | |
vehicle = trip.vehicle | |
gas_up(vehicle) | |
fill_water_tank(vehicle) | |
end | |
# ... | |
end | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# Recognizing Hidden Ducks | |
# 4 -------------------BAD | |
# A. CASE STATEMENTS (SEE ABOVE) | |
# B. #kind_of? and #is_a? | |
def prepare(preparer) | |
if preparer.kind_of?(Mechanic) | |
preparer.prepare_bicycles(bicycle) | |
elsif preparer.kind_of?(TripCoordinator) | |
preparer.buy_food(customers) | |
elsif preparer.kind_of?(Driver) | |
preparer.gas_up(vehicle) | |
preparer.fill_water_tank(vehicle) | |
end | |
end | |
# C. #responds_to? | |
def prepare(preparer) | |
if preparer.respond_to?(:prepare_bicycles) | |
preparer.prepare_bicycles(bicycle) | |
elsif preparer.respond_to?(:buy_food) | |
preparer.buy_food(customers) | |
elsif preparer.respond_to?(:gas_up) | |
preparer.gas_up(vehicle) | |
preparer.fill_water_tank(vehicle) | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment