本節書摘來自異步社群《重構:改善既有代碼的設計》一書中的第2章,第2.4節怎麼對經理說,作者【美】martin fowler,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
2.4 怎麼對經理說
“該怎麼跟經理說重構的事?”這是我最常被問到的一個問題。如果這位經理懂技術,那麼向他介紹重構應該不會很困難。如果這位經理隻對品質感興趣,那麼問題就集中到了“品質”上面。此時,在複審過程中使用重構就是一個不錯的辦法。大量研究結果顯示,技術複審是減少錯誤、提高開發速度的一條重要途徑。随便找一本關于複審、審查或軟體開發程式的書看看,從中找些最新引證,應該可以讓大多數經理認識複審的價值。然後你就可以把重構當作“将複審意見引入代碼内”的方法來使用,這很容易。
當然,很多經理嘴巴上說自己“品質驅動”,其實更多是“進度驅動”。這種情況下我會給他們一個較有争議的建議:不要告訴經理!
這是在搞破壞嗎?我不這樣想。軟體開發者都是專業人士。我們的工作就是盡可能快速創造出高效軟體。我的經驗告訴我,對于快速創造軟體,重構可帶來巨大幫助。如果需要添加新功能,而原本設計卻又使我無法友善地修改,我發現先重構再添加新功能會更快些。如果要修補錯誤,就得先了解軟體的工作方式,而我發現重構是了解軟體的最快方式。受進度驅動的經理要我盡可能快速完事,至于怎麼完成,那就是我的事了。我認為最快的方式就是重構,是以我就重構。
間接層和重構
——kent beck
“計算機科學是這樣一門科學:它相信所有問題都可以通過增加一個間接層來解決。”
——dennis debruler
由于軟體工程師對間接層如此醉心,你應該不會驚訝大多數重構都為程式引入了更多間接層。重構往往把大型對象拆成多個小型對象,把大型函數拆成多個小型函數。
但是,間接層是一柄雙刃劍。每次把一個東西分成兩份,你就需要多管理一個東西。如果某個對象委托另一對象,後者又委托另一對象,程式會愈加難以閱讀。
基于這個觀點,你會希望盡量減少間接層。
别急,夥計!間接層有它的價值。下面就是間接層的某些價值。
允許邏輯共享。比如說一個子函數在兩個不同的地點被調用,或超類中的某個函數被所有子類共享。
分開解釋意圖和實作。你可以選擇每個類和函數的名字,這給了你一個解釋自己意圖的機會。類或函數内部則解釋實作這個意圖的做法。如果類和函數内部又以更小單元的意圖來編寫,你所寫的代碼就可以描述其結構中的大部分重要資訊。
隔離變化。很可能我在兩個不同地點使用同一對象,其中一個地點我想改變對象行為,但如果修改了它,我就要冒同時影響兩處的風險。為此我做出一個子類,并在需要修改處引用這個子類。現在,我可以修改這個子類而不必承擔無意中影響另一處的風險。
封裝條件邏輯。對象有一種奇妙的機制:多态消息,可以靈活而清晰地表達條件邏輯。将條件邏輯轉化為消息形式,往往能降低代碼的重複、增加清晰度并提高彈性。
這就是重構遊戲:在保持系統現有行為的前提下,如何才能提高系統的品質或降低其成本,進而使它更有價值?
這個遊戲中最常見的變量就是:你如何看待你自己的程式。找出一個缺乏“間接層利益”之處,在不修改現有行為的前提下,為它加入一個間接層。現在你獲得了一個更有價值的程式,因為它有較高的品質,讓我們在明天(未來)受益。
請将這種方法與“小心翼翼的事前設計”做個比較。推測性設計總是試圖在任何一行代碼誕生之前就先讓系統擁有所有優秀品質,然後程式員将代碼塞進這個強健的骨架中就行了。這個過程的問題在于:太容易猜錯。如果運用重構,你就永遠不會面臨全盤錯誤的危險。程式自始至終都能保持一緻的行為,而你又有機會為程式添加更多價值不菲的品質。
還有一種比較少見的重構遊戲:找出不值得的間接層,并将它拿掉。這種間接層常以中介函數形式出現,它也許曾經有過貢獻,但芳華已逝。它也可能是個元件,你本來期望在不同地點共享它,或讓它表現出多态性,最終卻隻在一處用到。如果你找到這種“寄生式間接層”,請把它扔掉。如此一來你會獲得一個更有價值的程式,不是因為它取得了更多的優秀品質,而是因為它以更少的間接層獲得一樣多的優秀品質。