#はじめに
本題はここダックタイピングからです
##読者対象
読者対象はプログラミング初学者です。
といっても全くの初学者ではなく、Railsチュートリアルを終えたレベルと定義します。
##オブジェクト指向設計実践ガイド
オブエジェクト指向設計実践ガイドの記事は、他の方も書いてありますが、
一度に全部まとめたものが多かったです。
この記事は、オブエジェクト指向らしく、各章ごとに、単一責任に、シンプルさを意識して書きました。
余談ですが、とある弁護士が弁護士は六法全書を丸暗記してないが、各条文を見ただけで、関係ある条文、知識を思い出すそうです。
この記事は、オブジェクト指向設計実践ガイドってこんなこと書いてあったなーと思いだすための記事でもあります。
また、オブエジェクト指向設計実践ガイドを読んだことがなくても、こういうことが書いてあるとのかー、とさわりだけでも理解して頂けたら幸いです。
##オブジェクト指向設計実践ガイドで得た3つのポイント
リファクタリング前のコードを読み、コードの危うさを察知できる。
リファクタリングするために、より抽象的なコードの書き方を学べる。
gemなどの抽象的なコードを読解できる。
##一問一答
一問一答風の構成にしています。
リファクタリング前のコードを読み、コードの危うさ、嗅覚を養っていきましょう。
その後、リファクタリング前のコードの危うさを説明し、自分なりにリファクタリングしたコードを書いてみましょう。
最後に、もう一度、リファクタリング前のコードと、リファクタリング後のコードを読み比べ、
抽象的な思考、抽象的な書き方を共に学んでいきましょう。
#ダックタイピング
今回はダックタイピングというコードの書き方を説明します。
下記コードを読んで、このコードの危うさを説明し、自分なりにリファクタリングしたコードを書けるレベルに達しているなら、
オブエジェクト指向設計実践ガイドの第五章 「ダックタイピングでコストを削減する」、
この章を理解していると言えるでしょう。
##リファクタリング前
class Trip
attr_reader :bicycles,:customers,:vehicle
def prepare(prepares)
prepares.each do |preparer|
case preparer
when Mechanic
preparer.prepare_bicycles(bicycles)
when TripCordinator
preparer.buy_food(customers)
when Driver
preparer.gas_up(vehicle)
preparer.fill_water_tank(vehicle)
end
end
end
end
class Mechanic
def prepare_bicycles(bicycles)
bicycles.each {|bicycle| prepare_bicycle(bicycle)}
end
def prepare_bicycle(bicycle)
end
end
class TripCordinator
def buy_food(customers) ; end
end
class Driver
def gas_up(vehicle) ;end
def fill_water_tank(vehicle) ; end
end
trip =Trip.new
prepares = [Mechanic.new,TripCordinator.new]
trip.prepare(prepares)
###このコードの危険性
Tripクラスのprepareメソッドが各クラスに依存しすぎている。
機能が拡張するたびに、prepareメソッドを修正しないといけない。←バグのもと
##リファクタリング後
class Trip
attr_reader :bicycles,:customers,:vehicle
def prepare(prepares)
prepares.each do |preparer|
preparer.prepare_trip(self)
end
end
end
class Mechanic
def prepare_trip(trip)
trip.bicycles.each do |bicycle|
prepare_bicycle(bicycle)
end
end
def prepare_bicycle(bicycle) ;end
end
class TripCordinator
def prepare_trip(trip)
buy_food(trip.customer)
end
def buy_food(customers) ; end
end
class Driver
def prepare_trip(trip)
vehicle = trip.vehicle
gas_up(vehicle)
fill_water_tank(vehicle)
end
def gas_up(vehicle) ;end
def fill_water_tank(vehicle) ; end
end
trip =Trip.new
prepares = [Mechanic.new,TripCordinator.new]
trip.prepare(prepares)
##ダックタイピング
各クラスにprepare_trip(trip)メソッドを書くことによって、
Tripクラスのprepareメソッドがすっきりしました!!
このような書き方をダックタイピングといいます。
詳しくはオブジェクト指向設計実践ガイドに書いてあります。
#参考文献
オブエジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方