1. 程式人生 > >重構程式碼的7個階段

重構程式碼的7個階段

重構程式碼的7個階段

 2011年08月16日  陳皓 評論 77 條評論  32,336 人閱讀

-----------------------------------------------------------------

你曾去想重構一個很老的模組,但是你只看了一眼你就噁心極了。文件,奇怪的函式和類的命名,等等,整個模組就像一個帶著腳鐐的衣衫襤褸的人,雖然能走,但是其已經讓人感到很不舒服。面對這種情況,真正的程式設計師會是不會認輸的,他們會接受挑戰認真分析,那怕重寫也在所不惜。最終那個模組會被他們重構,就像以前和大家介紹過的

那些令人銷魂的程式設計方式中的屠宰式程式設計一樣。下面是重構程式碼的幾個階段,文章來自:The 7 stages of refactoring,下面的翻譯只是意譯。

第一階段 – 絕望

在你開始去檢視你想要重構的模組的,你會覺得好像很簡單,這裡需要改一個類,那裡需要改兩到三個函式,重寫幾個函式,看上去沒什麼大不了的,一兩天就搞定了。於是你著手開始重構,然後當你調整重構了一些程式碼,比如改了一些命名,修理了一些邏輯,漸漸地,你會發現這個怪物原來體型這麼大,你會看到與程式碼不符甚至含糊不清的註釋,完全摸不著頭腦的資料結構,還有一些看似不需要方法被調了幾次,你還會發現無法搞清一個函式呼叫鏈上的邏輯。你感到這個事可能一週都搞不定,你開始絕望了。

第二階段 – 找最簡單的做

你承認你要重構的這個模組就是一個可怕的怪物,不是一兩下就可以搞定的,於是你開始著幹一些簡單的事,比如重新命名一下幾個函式,移除一些程式碼的阻礙,產生幾個常量來消除magic number,等等,你知道這樣做至少不會讓程式碼變得更糟糕。

第三階段 – 再次絕望

但是接下來的事會讓你再次撞牆。你會發現那些程式碼的瑕疵是些不痛不癢的事,改正這些事完全於事無補,你應該要做的事就是重寫所有的東西。但是你卻沒有時間這麼幹,而這些程式碼剪不亂理還亂,耦合得太多,讓你再一次絕望。所以,你只能部分重寫那些不會花太多時間的部分,這樣至少可以讓這些老的程式碼能被更多的重用。雖然不完美,但是至少可以試試。

第四階段 – 開始樂觀

在你試著部分重構這個模組幾天之後,隨著重構了幾個單元后,雖然你發現改善程式碼的進度太慢了,但此時,你已知道程式碼應該要被改成什麼樣,你在痛苦之後也鎖定了那些那修改的類。是的,雖然你的時間預算已經超支,雖然要乾的事比較多,但你還是充滿希望,覺得那是值得的。你胸中的那團火又被點燃了。

第五階段  – 快速了結

在這個時候,你發現你已花了太多的時間,而情況越來越複雜,你感到你所面對的情況越來越讓你越到不安,你明白你自己已經陷入了困境。你原本以為只需要一次簡單的重構,然而現在你要面對的是重寫所有的東西。你開始意識到原因是因為你是一個完美主義者,你想讓程式碼變得完美。於是你開始在怠慢你文件,並想找到一個捷徑來重寫老的程式碼,你開始採用一些簡單而粗暴,快速而有點骯髒的方法。雖然不是很完美,但你就是這樣去做了。然後,你開始執行測試做UT,發現UT報告上全是紅色,幾乎全都失敗了,你恐慌了,於是快速地fix程式碼,然後讓UT 能工作。此時,你拍拍自己胸口,說到,沒問題 ,於是就把程式碼提交了。

第六階段 – 修改大量的Bug

你的重寫並不完美,雖然其過了測試,但是那些UT測試對於你的新的程式碼有點不太合適,雖然他們都沒有報錯,但是他們測試得範圍太小了,沒有覆蓋到所有的情況和邊界。所以,在這以後,你還需要幾周或是更長的時間不得不來修正越來越多的bug,這使得你的設計和程式碼在每一次quick-fix後就變得越來越難看。此時,程式碼已經不像你所期望的那樣完美了,但你依然覺得他還是比一開始要好一些。這個階段可能歷經幾個月。

第七階段  – 覺悟

經過了6個月,你重寫的模組又出了一個比較嚴重的bug。這讓你重構的那個模組變得更難堪。你發現出的這個問題是和當初的設計不一致,你還發現被你重構掉的那段老的程式碼並不是當初看上去的那麼壞,那段老的程式碼確實考慮到了一些你未曾考慮到的事情。這個時候,你團隊裡有人站出來說這個模組應該被重構或是重寫,而你卻不動聲色地一言不發,並希望那個站出來的人能在幾個月後能覺悟起來。

——————

不知道這是不是你的經歷,我經歷過很多次這樣的事。對於很多維護性質的專案,我犯過的錯誤讓我成了一個實實在在的保守派,我幾乎不敢動,那怕看到程式碼很不合口味。當然,那些從來沒有寫過程式碼的敏捷諮詢師一定會說用TDD或是UT可以讓你的重構更有效也更容易,因為這樣會讓他們顯得更我價值,但我想告訴你,這種脫離實際的說法很不負責任,這就好比說—— 我在殺豬的時候遇到了一些麻煩,因為我對豬的生理結構不清楚,或是這本來就是一頭畸形的豬,導致我殺的豬很難看,而偉大的敏捷諮詢師卻告訴我,要用一把更快更漂亮的刀。軟體開發永遠不是那麼簡單的事,殺豬也一樣。

------------------------------------------------------------------------

joeaniu說道:

2011年09月12日 01:16

站在什麼角度和立場去評判這件事情(重構超難的遺留程式碼),結論顯然是不一樣的。所以不說清楚立場,結論不免太片面。試著舉例:
1、一個有潔癖希望鍛鍊自己TDD能力,不甚關心公司短期利益,過高估計自己的程式設計師:多好的一個重構的範例啊,我要嘗試搞定它!(就如同一個新中醫遇到疑難雜症用猛藥似的)

2、一個傷了好多遍傷不起的老程式設計師:哈,這事兒誰動誰傻逼。看,新來的那個傻逼要蠢蠢欲動了,正好把我的bug的原因推給他,我好多休息下,我只管貼腐肉完成我的工作就行。老闆看見我這麼快,他那麼慢一定會對我更倚重。反正這個產品已經老得不能進化了, 遲早要趁SOA概念火爆,重新開發一個新的,沒必要為它吃力不討好,背黑鍋。

3、一個公司中層管理:我們的產品是夠老,加新功能很難,但老功能能用,客戶領導和我們關係很鐵,而且YY公司的產品比我們更差勁兒~,客戶領導不會因為我們爛而下臺,因為對手更爛! thank god!

4、客戶中層領導:MD,這個XX公司的東西實在難用,想加一點兒簡單的東西都推三阻四的。 哎管他呢,反正另外一家更爛,我不會有位置的危機,XX公司的銷售對我還不錯,就這樣吧!

5、客戶的老總:我們的效率比起國外同行來,還是有不少差距啊!不過我們有更多定價權,他們進來還受到限制:我們利潤比他們高,這多虧了社會主義的優越性啊~

6、政府官員:現在民族產業還不夠強大,全面開放的時機還不成熟,還需要大力扶持啊——政府扶持的錢不夠? 怎麼會? 多賣點兒地,多徵點房產改名稅,不就有了嗎!

7、老百姓(程式設計師): MD,稅又高了,房價又漲了,省吃儉用吧也不夠。 NND,不能幹程式設計師啊, 看那個搞sales的,積累一些業界客戶的關係,吃香的喝辣的,說不定榜上哪個老闆~~ 哦不,, 老闆的女兒,就少奮鬥10年啦!重構這東西能當飯吃嗎?都TM鬼扯淡!

….還可以推演更多,就不贅言了。

系統論給我的一個重要啟發是: 很多時候在一個系統內部看不出問題,只要站在一個更大範圍的系統去觀察,說不定就會找到原因。 上述關於重構的故事的我的結論是: 在一個效率並非最重要競爭要素的市場機制裡,單純的糾結重構這樣的效率手段應不應該做, 這樣是不智的。 說到底是一個利益問題。

 

--------------------------------------------

Gavin說道:

2013年04月12日 18:26

重構這個事情,越早越好。最好是原班人馬。不然就別幹。或者想都不要想。

 

-----------------------------------------------

sumai說道:

2011年08月16日 09:14

我們公司有一些程式碼,存在的時間超過了20年。在那個磁碟空間以MB來計算的年代下,程式碼裡的函式名變數名極其精簡且晦澀難懂。C風格的程式碼和後來新加的C++風格的混在一起。最恐怖的一個核心函式,裡面只有一個switch/case但是有3000行之多。當我第一次看到這些程式碼時實在很難理解為什麼這麼多年沒有人重構過,至少讓程式碼的邏輯看起來清晰一些。但幾年以後再看這些程式碼,幾乎到處都有defect fix — 這不是說明程式碼爛,而是曾經有大量的QA和數百萬的使用者在20多年的時間裡不斷測試這些程式碼,把所有能碰到的極端情況都測到了,以至於那些貌似很醜陋的程式碼實際上極其穩定。

在這種情況下,如果還有人想去重構一把,那隻能是腦筋秀逗。

回覆

  1. 陳皓說道:

    2011年08月16日 09:56

    @sumai,你經歷過的這個事和我經歷過的一個太像了,我經歷過2000多個case,一個switch語句1萬多行,但是不敢動啊,因為那是10年來的程式碼,執行地沒有問題。