1. 程式人生 > >重構的幾點注意事項

重構的幾點注意事項

1. 重構是減緩程式碼腐化的有效武器

現在很少有軟體完全是從0開始開發,也很少有軟體有很短的生命週期(2年)以下。那麼,換句話說,很多時候你拿到的都是既有程式碼,它能工作,也許它的設計很好,也許很亂,但它肯定能工作。即使是優質的專案,當初的設計,架構非常合理,程式碼很優質,但隨著時間的推移,人員的變動,不斷的修復Bug,不斷的新增新功能,程式碼總是會腐化的。長期維護的專案,最大的腐化點就是在沒有完全理解程式碼的情況下做修改,但這卻是經常發生的事情,想想新進專案的人,以及管理層的壓力,導致Bug或者新功能很快上去,但修改者還沒有完全理解程式碼,所做的修改肯定會有問題。這個時候就需要不斷的重構,當你對程式碼有了新的認識的時候,你就會明白為什麼作者那樣寫,知道如何修改才是最佳方案。通過重構可以把腐化的程式碼改成優質的程式碼。

2. 關鍵是要用心

重構是程式設計的一種技巧,而程式設計又是一種社會活動(《程式設計心理學習》),所以人的態度及所花的心思就起到決定性作用。如果不用心去做,那即使再好的技巧也是空談。要肯花時間和心思在程式碼上面,思考作者為何那樣寫,思考可改進的空間,然後測試,再做出修改嘗試,直到最終改成優質程式碼。這是一個很費心思的過程,甚至比重新寫還困難:重新寫你只需要理解需求即可;但改重構需要理解現有的程式碼,這通常都是一個很痛苦的過程,因為程式碼通常都很難讀懂,充滿各種壞味道(當然,如果程式碼讀起來很好,寫的很優美,沒有壞味道,也就用不著重構了),這也是很多人不願意重構的原因:即然程式碼能工作,何必理那堆濫攤子!

所以,關鍵還是態度和用心

3. 不要為了重構而重構

這種情況通常是剛讀了書之後或者看了某篇部落格之後,熱血沸騰:我們的程式碼壞味道太多了,很我必要重構。這時就要止住,重構需要冷靜的思考,認真的對待,並且在理解程式碼的情況下進行,並嚴格的進行測試,否則就是在搞破壞。頭腦發熱式的大刀闊斧的重構會帶來更多的問題。

4. 注意重構的前提

這個Martin已經講了,這裡做些補充:首先就是政策允許,也即管理層允許隨時修改程式碼,這聽起來可笑,但有些公司確實不允許隨便改程式碼(特別是對於成熟專案),還有時間允許,如果你24小時都在改Bug,也真的很難抽時間去重構(這樣的公司確實存在);其次,就是對程式碼要熟悉:明白其目的,作者為啥那樣寫;最後就是做足測試,包括重構前和重構後,Martin講要用單元測試,但很不幸現實中的專案很少有單元測試,現補也不太現實,其實手動測試也是一樣的。

5. 小步前進,時刻保持程式碼可工作

這非常重要,雖然程式碼很亂,但不能大刀闊斧的大範圍的搬移方法,拆分類等,這樣做的結果只有一個:程式碼不會正常工作,導致混亂漫長的除錯。要小步前進,雖然有很多方法不應該在現有的類中,但也要一次一個的移動,以確保我們沒在搞破壞。同時要不斷的測試,以保證程式碼時刻都能正常工作(因為要如此頻繁的進行測試,所以Martin才會把單元測試當作前提,但手動測試也一樣)。這一點從Martin的書中也能體現到,很多方法都會拆分成很多小步驟,每次一個步驟,然後測試,直到最後完成。

6. 重構是一個長期計劃,每天都要進行

寫出程式碼後要重構,維護程式碼時更要重構。這是一個長期的計劃,不能像改Bug一樣,改完了就不管了。也就是說每當看到程式碼有壞味道時就進行重構,而不是等到什麼時候才進行。

7. 重構是工作的一部分但不是全部

不要把一整天的時間,或者一整星期的時間都花在重構上面,這樣做很容易過度重構。重構應該穿插在日常的工作當中,比如寫程式碼時進行或者改Bug時進行或者新增新功能時進行。但重構不應該是主要或全部工作內容。重構是改善現有程式碼設計,前提是程式碼能正常工作,所以首要的任務是讓程式碼能正常工作。

8. 沒有最好,只有更好

好程式碼與壞程式碼沒有明顯的界線區別,不像考試:60分及格,59就掛。好與壞都是抽象概念,相對主觀,可能你認為好的東西在別人眼中很濫,反之亦然。所以就要不斷的思考,當覺得有改進的地方時就去改進,而不是停步不前。

9. 時代變遷

Martin的書著於1999年,現已是十多年光景,軟體界也發生了不少變化,程式設計方法也有了不少改進,所以某些方法可能現在不太適用。這就需要在用的時候要思考,不要死讀書,更不要讀死書。像8.13 Replace Type Code with Class也可以用enum來進行,Java是強型別語言,enum也會進行型別檢查。再如10.13 Encapsulate Downcast就要用Generics。

10. 這本書要讀二遍,並放在觸手可及的地方

技術書籍至少要讀二遍:第一遍快速瀏覽書中有哪些內容,以決定是否值得繼續讀;第二遍找出感興趣的章節,逐字逐句的仔細咀嚼。

本書由於重構手法太多,每種手法都有其動機和詳細方法步驟,這個不可能全記得住,至少我記不住。所以就需要放在觸手可及的地方,每當覺得有類似手法可以用時,就把書找出來再分析一番,以確保沒有亂用。

11. 掌握好準則

書中很多手法都是相反的,比如Extract Method和Inline Method,它們的作用恰恰相反。這就需要在用的時候思考,找到足夠的理由才進行,因為沒有明顯的線索告訴你到底該進行Extract Method還是Inline Method。這就需要去嘗試,去思考,哪種效果更好用哪種,如果實在不知道就隨便用一個,隨著時間的推移會發現它的利與弊,然後再進行調整。

12. 重構的目的

重構的目的是:改善現有程式碼的設計,也就是說把程式碼變得更好。如果你不希望程式碼變得更好,或者程式碼變好了對你也沒啥好處(你是臨時工或外包),或者你覺得現有程式碼就挺好的,那其實也沒有必要花時間去重構,還不如去上上網,扯扯蛋!

但,如果你是一個優秀的猿嬡,或者想成為一個優秀的猿嬡,最好還是重構一下吧!閒著也是閒著,何不鍛鍊一下自己呢?雖然改善的是程式碼,但更多的還是自己的技能啊!

13. 去哪裡重構

也許你的專案的環境不允許你隨意改程式碼,或者你對專案沒興趣,或者感覺專案已經無藥可救了,沒關係可以到開源世界來!現在開源世界有一種叫做Refactotum的活動,它是一群開發者約好一個時間,然後把一個開源專案(或其部分原始碼)下載下來,執行其單元測試,然後重構,重構提交程式碼。