リファクタリングの原理原則
「コンピュータが理解できるコードは誰でも書ける。優れたプログラマが書くのは、人間が理解できるコードだ」
リファクタリングはコードの保守をする中でとっても大切なことは分かっているけど、原理原則を持っていない。原理原則が欲しいので、書籍「リファクタリング:Rubyエディション」を読んで、原理原則を手に入れようとしている。まだ読んでる途中だけど、アウトプット。書いてあるコードを丸写しするのではなく、自分なりにコードを書き直す事で理解した。
原理原則の前に大切なこと
リファクタリングでは、テストが命綱になる。リファクタリングが成功するかどうかは、よいテストが用意できているかどうかによって左右される。テストは、後でプログラムを書き換えなければならなくなった時の安全弁になるので、十分に時間をかけて作って良い。そして、テストは自己診断テストでなければならない。リファクタリングでは、プログラムを少しずつ変更すること。そうすれば、間違えても簡単にバグを見つけられる。
メソッドの抽出(Extract Method)(P31)
新しいメソッドにスコープが限られている変数、つまりローカル変数と引数になるべきものを元のコードから探す。たとえば、human と total がそれに当たるとしよう。そのうち、human はコード内で変更されないが、total は変更される。変更されない変数は引数として渡せるが、変更される変数はもう少し慎重に扱わなければならない。そういう変数が1つだけなら、戻り値として返せる。一時変数 total は、ループ開始時に 0 に初期化され、 case文に入るまで変更されないので、新メソッドの戻り値を代入出来る。
リファクタリング前
class Keiri def initialize @human = ["adult", "children"] end def fare_total result = "運賃合計: " total = 0 @human.each do | human | case human when "adult" total += 200 when "children" total += 100 end end # 結果を出力 result + "#{total}" end end keiri = Keiri.new puts keiri.fare_total
リファクタリング後
class Keiri def initialize @human = ["adult", "children"] end def fare_total result = "運賃合計: " total = 0 @human.each do | human | total += fare(human) end # 運賃合計を出力 result + "#{total}" end # 運賃 def fare(human_kind) case human_kind when "adult" result = 200 when "children" result = 100 end result end end keiri = Keiri.new puts keiri.fare_total
メソッドの移動(Move Method)(P36)
メソッドの抽出の続き。クラス Keiri は fare メソッドを持っているが、実は運賃には複数種類があることが発覚。そのため、クラス Fare を作成して、fareメソッドを移動することにした。
リファクタリング前
class Keiri def initialize @human = ["adult", "children"] end def fare_total result = "運賃合計: " total = 0 @human.each do | human | total += fare(human) end # 運賃合計を出力 result + "#{total}" end # 運賃 def fare(human_kind) case human_kind when "adult" result = 200 when "children" result = 100 end result end end keiri = Keiri.new puts keiri.fare_total
リファクタリング後
class Keiri def initialize @human = ["adult", "children"] end def bus_fare_total result = "運賃合計: " total = 0 @human.each do | human | total += Fare.bus(human) end # 運賃合計を出力 result + "#{total}" end end class Fare # バス運賃 def self.bus(human_kind) case human_kind when "adult" result = 200 when "children" result = 100 end result end #高速バス運賃 def self.expressway_bus(human_kind) case human_kind when "adult" result = 3000 when "children" result = 1500 end result end end keiri = Keiri.new puts keiri.bus_fare_total
一時変数から問い合わせメソッドへ(Replace Temp with Query)(P41)
以下は、極端な例だが・・・言いたいことは同じはず。
リファクタリング前
def hoge total = 0 @human.each do |human| total = human.fare total += total end puts total end
リファクタリング後
def hoge total = 0 @human.each do |human| total += human.fare end puts total end
ループからコレクションクロージャメソッドへ(Replace Loop with Collection Closure Method)(P49)
リファクタリング前
class Hoge def total result = 0 [1, 2, 3, 4, 5].each do |n| result += n end result end
リファクタリング後
class Hoge def total [1, 2, 3, 4, 5].inject(0) { |total, n| total + n } end end
書籍紹介
- 作者: Jay Fields,Shane Harvie,Martin Fowler,Kent Beck,長尾高弘
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2010/02/27
- メディア: 大型本
- 購入: 9人 クリック: 321回
- この商品を含むブログ (49件) を見る