前面提到我們可以用 Extract 系列招式來抽取出符合單一職責的方法、變數或類別,但過做得太過頭,往往會導致簡單的邏輯被剪碎成難以理解的樣子。這時候就可以使用 inline 把程式碼整理到同一個 scope 中。
Inline 雖然有個中文翻譯叫內聯,在經驗上很多人沒有辦法理解它的意思。在程式中,每一次的方法/函式呼叫,都會往 call stack 加上一層,造成額外的成本。所以有時候聰明的編譯器會幫你把那個函式裡面的內容「塞回」到呼叫的那一行。在重構時,inline 指的則是在原始碼的時期就「塞回」去呼叫處。
看看這個例子,加法是一個非常簡單的運算,多抽一層方法並不會很好理解。
private const int fee = 200;
public int CalculateFinalPrice(int price) {
var result = Add(price, fee);
return result;
}
private int Add(int augend, int addend) {
return augend + addend;
}
Inline Method 過後的結果會是這樣,把 Add 方法中的內容「塞回」呼叫的那行。
private const int fee = 200;
public int CalculateFinalPrice(int price) {
var result = price + fee;
return result;
}
而 result 這個變數也沒有什麼解釋的意涵,Inline Vairable 的結果會是這樣,把 result 的賦值「塞回」呼叫的那行。
private const int fee = 200;
public int CalculateFinalPrice(int price) {
return price + fee;
}
回到 Rider 上,看看昨天還在用的 RsaHelper,不知道誰抽了方法。抽方法本身沒問題,但是他抽的方式把解密的邏輯切得七零八落、難以閱讀,看看那個 out,真希望這位同事也早日 out 走。
選到那個醜醜的方法上按 Refactor This
,可以看到有個 Inline Method 可以用。
按下去之後跳出一個彈窗,問我 inline 後要不要保留那個方法,當然是直接移掉,誰要留啊。
成功把那段程式碼「塞回」原本的地方。我看到有個 "var maxBlockSize = maxBlockSize1",這是 Rider 幫我建立的暫時變數,我也不需要它。
選擇 Inline Variable。
成功移除掉這個暫時變數,掰掰。
下面那個 private Decrypt 不僅跟原本的 public Decrypt 同名,解釋性也不夠好,也把它先 inline 回來吧。
完成。
我看到下面那個 "var request" 的暫時變數也沒必要,一樣 inline。順便把 maxBlockSize1 給 rename 一下。
完成!
Inline 作為 Extract 的逆操作,一開始接觸的時候可能會覺得幹麻要把做過的事又還原回去。實務上,因為我們很難一次就抽象出正確邏輯、分離出正確的職責,所以時常需要把所有東西先擺在一起看看,整理整理後再分開,如此往復循環,最終才會找到最適合的形狀。