l

2014年4月7日 星期一

什麼是Refactoring?

Mar. 21 07:20~08:57

螢幕截圖 2014-03-21 08.37.31

 

看過Martin Fowler所寫的〈Refactoring: Improving the Design of Existing Code〉的鄉民應該都知道,refactoring(重構)的定義就是:「在不改變軟體的外在行為之下,改善既有軟體的內部設計」。如何改善?先判斷軟體中所存在的壞味道(smell),然後套用重構來移除這些壞味道。每一條軟體重構就是一些告訴開發人員要如何移除各種壞味道的小步驟。

今天Teddy要在Alexander的context-form-force的框架中,來探討refactoring。請看上圖左方,依據Alexander對於設計的定義:「設計就是尋找context與form的界線」。因為refactoring是「改善既有軟體的內部設計」,因此開發人員所面對的問題,不是從頭產生一個新的設計,而是在「既有設計」中想辦法去改善它。也就是說,這時候開發人員手邊已經有了「既有設計」(form)以及它所存在的context。

接下來首先要問的問題是:「既有設計與它的context分別是什麼?」從refactoring的角度來看,context就是codebase(既有系統的所有原始碼),而form就是要重構的對象,可能是表示式、一串參數、變數名稱、method、class、繼承架構、模組等。由於這些已經存在的form受到force(作用力)的擠壓,無法保持「宇宙和諧」,因此我們覺得現有的設計不「合適」(fitness)。

***

鄉民甲:壞味道是不是就是你說的force?

這個問題非常好,壞味道是已經存在form裡面的一種現象,所以它是form的一部分,並不是force。舉個例子,long method(過長函數)是一個壞味道,就表示有這個壞味道的method程式碼行數非常多。所以form包含壞味道。

壞味道只是一種「force懶人包」,它本身並不是force,force是壞味道之所以是壞味道的原因(迷之音:懶人包看太多,人真的會變懶挑眉質疑)。以long method為例,你有一個很長的method這只是一個現象,如果能看出來為什麼method行數太長不好的「原因」,就可以找到force。

同樣以long method為例,Kent Beck和Martin Fowler(Bad Smells in Code這一章由他們兩人合寫)在書中提到explanation(解釋)、sharing(共享)、choosing(選擇)是short method的優點,換句話說,這三點就是long method最明顯的force。

螢幕截圖 2014-03-21 08.35.35

 

因為long method無法平衡(balance)這些force,所以我們認為這個「具有long method的form」不fit(合適)目前的context(codebase)。

***

扯了這麼多,refactoring終於要出場了。藉由一連串修改form的小動作(套用refactoring),把壞味道由form裡面移除,請參考下圖右方。這時候新的form已經和原來的form不一樣了,例如把原本的long method套用Extract Method重構抽離出若干個short method,然後在原本的method中呼叫這些被抽離出去的method。原本form裡面的一些程式碼因為套用Extract Method之後變成context的一部分,但從context的角度來看,原本form的「外在行為(功能)」並沒有改變。

螢幕截圖 2014-03-21 08.37.31

 

重構之後force有沒有消失?沒有,消失的是壞味道,不是force。但是因為重構之後新的form改變了,已經可以平衡原本的force,所以我們說新的form和context非常「速配」。

***

《Refactoring》書中提到22個壞味道,包含:duplicated code、long method、large class、long parameter list、divergent change、shotgun surgery、feature envy、data clumps、primitive obsession、switch statements、parallel inheritance hierarchies、lazy class、speculative generality、temporary field、message chains、middle man、inappropriate intimacy、alternative classes with different interfaces、incomplete library class、data class、refused bequest、comments。這些「force懶人包」整理得非常棒,很可惜Kent Beck和Martin Fowler並沒有非常明確的將每一個壞味道背後的force列出來(有些壞味道有提到force,有些則是用敘述性的文字隱約說明,要靠讀者自行從文字敘述中提煉出來),因此可能導致鄉民們把這些壞味道都背下來,但卻不一定非常清楚造成它們「變壞」的背後原因。

***

友藏內心獨白:原來如此。

2 則留言:

  1. 说的太过冗长,明明很好解释的

    回覆刪除
  2. 重構不一定是因為Bad smell,重構的方法有些如果你仔細看,其實只是一體兩面的東西,至於為何你要採用某種重構方法而不採用某種重構方法,還是得因地制宜。

    回覆刪除