Refactoring: Ruby Edition, Chapter 1

最近開始讀 Refatoring: Ruby Edition,記錄有趣的部分。

1.1.1

突然一看到 attr_reader 竟然忘記是在幹嘛的...趕快查了下恢復記憶,其實就是設定 getter & setter

1.3

  • case 看起來就很適合提煉出來專門放到一個 method 裡
  • 「提煉沒做好,就會引入 bug」,這個引入實在是太貼切了,程式沒寫好就會變成吳三桂
  • 首先看 method 內部的變量,包括 local variable 和 parameter
  • 這裡開始重構,說要用到測試來檢查,不過還沒看到測試的 code,難道是要自己寫?
  • 「代碼必須能展示自身的用途」,變量的名字則是關鍵
  • 「一邊閱讀代碼,一邊重構,在理解程序的同時將它們嵌入到代碼裡,以防止將來忘記從中領悟到的東西」

1.3.1

  • 觀察 method 所使用的信息來源,一個 method 應該放在它所使用數據所在的對象裡。
  • 這裡的 UML 圖還滿有趣的,可以圖像化剛才切斷了哪裡冗長的程序,分門別類重新擺放了哪些 method
  • Replace Temp with Query

1.3.3

臨時變量看起來滿被作者討厭的,不停地被移除,這邊有個臨時變量 total_amount 的位置在 iteration 裡,所以被移出來的時候連 iteration 都要一起帶入

  def statement
    total_amount, frequent_renter_points = 0, 0
    result = "Rental Record for #{@name}\n"
    @rentals.each do |element|
      frequent_renter_points += element.frequent_renter_points
      result += "\t" + element.movie.title + "\t" + element.charge.to_s + "\n"
      total_amount += element.charge
    end
    # add footer lines
    result += "Amount owned is #{total_amount}\n"
    result += "You earned #{frequent_renter_points} frequent renter points"
    result
  end

移到 private method 裡,反正算完之後只有在 result += "Amount owned is #{total_amount}\n" 出現

  private
  
  def total_charge
    result = 0
    @rentals.each do |element|
      result = element.charge
    end
    result
  end

這個簡化讓我覺得舒服

  def total_charge
    result = 0
    @rentals.each do |element|
      result = element.charge
    end
    result
  end

可以用 inject 這個處理總和的方法再縮成

  def total_charge
    @rentals.inject(0) { |sum, rental| sum + rental.charge }
  end

1.4

看到目前為止的感覺,refactor 很重要的一件事就是判斷 method 調用的變量和 class 的關係,凡是抵觸一律搬走,需要的變量再另外傳進去,總之自己的數據自己操作,不是自己的數據就還給人家去操作