l

2016年8月2日 星期二

軟體重構工具的四個誤區

August 01 13:14~14:00 21:15~23:00

螢幕截圖 2016-08-01 23.02.02

 

最近比較多時間與心思都花在讀禪學、佛學與哲學的書,為了不要把「搞笑談軟工」變成「搞笑談玄學」,改採取短打策略,介紹一些相對比較不花腦筋的短篇論文給鄉民們參考。今天繼續介紹IEEE Software的文章,這一篇名為「Refactoring Myths」的文章發表於2015年11/12月,討論關於自動化重構工具的四點迷思。

所謂神話或傳說(myths)是一種可能傳達部分真相,但是沒有傳達全部真相的故事,也可以翻譯成誤區或迷思。作者在文章中提到四點對於自動化重構工具的誤區,分別是:意圖(Intent)原則(Principle)強建度(Robustness)支援(Support)

***

意圖(Intent)

第一個誤區是認為重構工具之所以有用是因為它可以幫助開發人員自動化完成單調乏味的設計改變。重構無庸置疑是一種設計活動,Martin Fowler著名的重構書籍《Refactoring: Improving the Design of Existing Code》的書名就告訴我們重構可以改善現存程式碼的設計。重構工具可以幫助自動化達成這些設計改變,例如在繼承架構中移動類別、封裝資料、用界面取代類別。但是,有研究指出開發人員最常使用的重構功能其實是重新命名區域變數或private method、抽離函數、抽離區域變數或內嵌區域變數這類的小重構動作。這類重構比較屬於編碼風格(coding style)而非設計(design)層次

所以原本針對「重構工具可以協助自動化完成單調乏味的設計改變」的看法,應該修正為「重構工具可以協助自動化完成單調乏味的程式碼改變,這些改變對於設計有不同層度的影響。」設計是開發人員的責任,並不是重構工具的責任。工具可以協助開發人員將一些瑣碎、重複的動作自動化(例如Rename重構),但是開發人員必須自己清楚知道這些動作所帶來的期待結果是什麼,無論這些結果是屬於實作或是設計層次。

因此作者認為可預測性(predictability)對於開發人員使用或不使用哪些重構功能扮演重要的角色。如果一個重構的結果具有更高的可預測性,開發人員越可能組合它們來產生設計層次的改變。

***

原則(Principle)

重構的定義就是「在不改變行為的前提之下改變軟體的結構以達到改善設計的目的。」因此在執行重構活動的時候「確保重構沒有改變軟體行為便成為一個普遍接受的原則。換句話說,如果在改善設計的過程中改變了程式行為,這種改善活動就不能稱為重構。

但是,對於開發人員而言行為確保並非主要目標,有時候自動化重構即使稍微改變了程式行為,開發人員還是願意去執行此類重構。例如,在程式存在語法錯誤無法編譯的情況下,程式的行為根本還無法定義,此時開發人員還是有可能想要透過Rename或是Extract Method來重構部分程式區塊。

就算程式碼可以編譯,自動化重構還是可能改變程式行為。例如Rename可能讓透過Reflection呼叫函數的程式碼無法執行,Extract Method可能破壞直接存取stack trace的程式碼(因為Extract Method改變函數呼叫順序,因此也改變了stack trace的內容)。

實務上如果可以稍微放鬆原始重構的定義,把行為確保(behavior preservation)放寬為行為增強(behavior-enhancing)—採取定義明確的小步驟來修改程式行為,也許會更合適。關於這一點Teddy幾年前在研究例外處理重構(exception handling refactorng)時也遇到此問題,例外處理重構雖然並不會改變程式的「正常行為」(normal behavior)但卻會改變異常行為(exceptional behavior),所以廣義上來講也是改變了系統的行為。如果把重構定義稍微放寬為行為增強(behavior-enhancing),又或者把行為增強視為與重構互補的程式碼轉換,比較能夠涵蓋實務上各種不同的情況。

***

強建度(Robustness)

第三個迷思就是開發人員普遍認為自動化重構工具應該很可靠,但實際上並非如此。如果一個工具不可靠,開發人員就不會使用它。自動化重構工具一般來講讓人覺得很強健、很可靠,但實際上這些工具雖然足夠可靠,但並非毫無錯誤,所幸大部分的錯誤都發生在不重要的地方。

作者測試了Eclipse的JDT、CDT,還有NetBeans和IntelliJ IDEA、Visual Assist X的重構功能,發現若干新的bug還有遭遇到操作失敗的情況。最後作者提到Refaster這個由Google所開發的重構工具,針對工具的可靠性它採取不同的策略—編譯錯誤和測試案例要負責確保程式碼轉換(重構)是否破壞原本程式行為,工具只是提供簡單的字句替換,提供替換前與替換後的程式碼範例給開發人員參考,並不負責檢查重構前後行為是否一致

***

支援(Support)

最後一個迷思就是將自動化重構工具整合到IDE(整合開發工具例如Eclipse或Visual Studio.Net)是最佳吸引開發人員使用的途徑。作者認為重構工具必須要是開發人員已經熟悉環境的一部分,但這個環境不一定是IDE,可以是Vim、Notepad++或Sublime Text

***

結論

之前還在念書的時候曾經和好幾屆的學弟一起開發過Eclispe上的例外處理重構工具,對於這篇文章所提到的這四點很有感覺。這四個誤區看起來好像沒什麼,但實際上卻可能在無形中阻礙了開發人員套用重構。

幾年前遇到一位很有經驗的架構師,和他聊到design pattern與重構,他非常堅持「重構的目的就是要套用design pattern」,這就採到了這篇文章所講的第一個誤區。另外,許多人對於重構絕對不能改變程式行為的堅持,有時候會有點綁手綁腳,導致在套用重構時心態過於保守。

重構這個名詞問世至今已超過20年,也成為軟體開發主要的活動之一。實務上總覺得開發人員嘴上經常提到重構,但身體卻鮮少落實。對於深入研究重構有興趣的鄉民,可以從這篇文章得到一些啟發。

***

友藏內心獨白:我知道,你沒時間,專案已經延遲很久了;結案。

沒有留言:

張貼留言