代碼重構的實戰經驗和那些坑

爲何咱們以爲有必要從頭重寫軟件呢?

在第一次編寫系統代碼時,咱們的時間表十分緊迫,必須與時間賽跑,在計劃時間內趕完進度。所以不管是設計討論,仍是審查會議都沒花太長時間——咱們沒有時間浪費在這上面——只能匆匆完成一個功能、快速測試,而後趕着去作下一個。咱們與別的公司共享辦公空間,我還記得其餘公司的軟件開發都會花很長時間作設計、討論架構,再花上數週討論設計模型。html

 

除了設計倉促,本來的系統寫得不差,整體來講架構也不錯。其中有些意大利麪條式的代碼,是公司以前作概念驗證時留下的,由於這些代碼能用,再加上工期緊張,當時咱們沒有去碰。但後來咱們不考慮執行優化改進,卻決定要從頭重寫代碼的緣由在於:前端

 

  • 老舊代碼很糟糕,很難維護;java

  • 「單一總體式的java架構」對咱們的將來發展不利,沒法支持有6千萬移動用戶以及多站點部署的大型運行商;程序員

  • 我想要嘗試炫酷的新技術,好比Apache Cassandra、虛擬化技術、二進制協議、SOA等等。數據庫

 

結果很不幸:咱們說服了全公司以及董事會,實現了願望。架構

 

代碼重寫之旅

正式的開發時間是從2012年春天開始的,咱們將2013年1月末設定爲發佈時間。因爲計劃太過龐大,咱們須要更多的人,因而在印度聘請了顧問與幾個遠程開發者。可是,咱們沒有充分預期到維護本來系統、進行新的開發工做與理解客戶需求這些並行起來的工做量。工具

還記得我在文章最開始說過,咱們有一個真實客戶麼?這位客戶是南美最大的移動運營商之一。在咱們開發的系統投入使用後,他們開始對變動和新功能提出要求,所以咱們只能繼續更新原來的系統。可是,因爲這個系統將會被廢棄,在更新時咱們總有些敷衍了事,儘量找藉口拒絕了客戶許多的新功能需求。結果致使了工期拖延,沒能在原定的deadline完成進度。事實上,咱們的進度拖延了整整8個月。性能

不過咱們仍是先說說結果吧:當項目終於完工時,新系統看起來很是棒,知足全部需求。咱們作了負載測試,結果顯示新系統能很容易地支持超過1億的用戶,配置集中,查看圖表的UI工具也很美觀,是時候廢棄舊系統,改換新系統了……學習

可是客戶拒絕了升級的請求:本來的系統已經得到了普遍應用,他們的用戶已經開始依賴舊系統了,他們徹底不想冒風險。長話短說,浪費了幾個月以後咱們收效甚微。該項目正式宣告失敗。測試

咱們學到的經驗

  • 大多狀況下都不應從頭重寫代碼。咱們重寫代碼的緣由是錯誤的,儘管一部分代碼不怎麼樣,若是咱們花些時間閱讀理解源代碼,就能夠經過重構修復問題。對架構的可擴展性及性能咱們確實有顧慮,擔憂它沒法支持複雜的業務邏輯,但徹底能夠逐步進行修復。

  • 從頭重寫系統對用戶來講沒有價值。新技術與流行詞對工程師團隊來講看似很酷,但若是不能按照客戶需求提供新的功能,則毫無心義。

  • 咱們在集中精力重寫代碼時,錯過了真正的機會。之前咱們給客戶提供了一個很是基本的「站點分析工具(Web Tool)」供他們查看圖表與報告。但隨着內容愈來愈多,他們開始要求增長新功能,好比實時圖表、訪問級別等等。因爲咱們不打算繼續沿用舊代碼,時間也不足夠,就敷衍着要麼拒絕了新需求,要麼湊合了事。結果最後客戶再也不使用這個工具了,他們堅持經過郵件來發報告。原本咱們還有另外一個機會來構建一個有緊迫需求的強健分析平臺。

  • 我低估了在維護舊系統的同時,開發新系統所須要的工做量。咱們本來預計一個月能有3到5次需求,結果倒是預計數量的三倍。

  • 咱們覺得:因爲沒能花上很多天討論合適的設計模型與實例,代碼就會很難閱讀與維護,結果事實上我在較大公司所見過的最專業代碼,比咱們的代碼還要糟糕兩倍。所以,在這一點上咱們大錯特錯。

 

什麼時候須要重寫代碼

 

Joel Spolsky強烈反對重寫代碼,他建議你們都不要這樣作。不過我不是特別認同:有時候逐步優化與重構很是困難,惟一讀懂代碼的方式就是重寫。此外軟件開發人員喜歡編寫代碼,創造新東西——閱讀別人寫的代碼,嘗試理解他們的代碼與「思惟抽象」會很無聊。不過,優秀的程序員也是優秀的維護者。

若是你想要重寫代碼,必定要出於正確的理由,並有着合適的計劃。好比:

  • 有時候在發佈新版好久以後,老舊代碼仍需維護,維護兩個版本的代碼須要耗費大量工做,在開始重寫前請根據項目規模評估所需的時間與資源。

  • 想一想其餘失去的機會,並比較任務的優先級。

  • 重寫大型系統比小型系統風險更高,考慮一下可否逐步重寫。咱們同時執行了如下幾項工做:切換到新的數據庫、使用「SOA」架構、更換爲二進制協議,其實本能夠逐步執行這些更換。

  • 考慮開發者的偏見。在開發者想要學習新技術或新語言的時候,他們會想要使用這些來重寫某些代碼。不過我不反對這樣作,這也是良好環境與文化的標誌,但應當將它與風險和機遇作比較。

Michael Meadows對什麼時候有須要進行「大型」重寫有着很好的見解

技術上

  • 組件的耦合度很高,沒法單獨對某個組件進行修改。從新設計單個組件會致使一連串的變化,不只會影響到相鄰的組件,甚至間接影響到全部的組件。

  • 技術堆棧太過複雜,將來狀態設計須要變動不少的基礎架構。出於這個緣由執行徹底重寫十分必要,逐步從新設計在這種狀況下沒有優點。

  • 從新設計單個組件不管如何都會致使對該組件的重寫,在現有設計中沒有能夠插入新功能的地方。這種狀況下逐步從新設計沒有優點。

政策上

  • 贊助商沒法理解逐步從新設計須要對項目進行長期投入。不可避免的是:大多數公司對於在逐步從新設計上繼續耗費預算沒有興趣。在徹底重寫代碼時,這種現象也很難避免,但贊助商更願意繼續投入,由於他們不想用着半成品的新系統與部分過期的舊系統。

  • 系統用戶更習慣使用「本來的界面」:在這種狀況下,政策上不會容許修改系統的重要部分(前端)。但若是徹底從頭開始重寫,則會繞過這個問題。用戶還會堅持使用「相同的界面」,但此次你反擊的理由更爲充足。要記得:逐步從新設計的總成本老是要高於完整重寫代碼,但通常來講對企業的影響更小一些。在我看來,若是重寫理由充足,公司又有超級優秀的開發者,那麼就開工吧。

放棄正在開發的項目很危險:浪費大量的時間和金錢重複實現已有功能,同時還會放棄實現新功能的機會,有可能激怒客戶並致使工做計劃推遲。若是你正在重寫代碼,那是你的權力,不過請確保這麼作的理由正確,同時瞭解風險也作了相關計劃。

原文連接:http://www.colotu.com/html/gcs/49.html

相關文章
相關標籤/搜索