如何在遺留程式碼基礎上開發

infoq發表於2013-03-20

  對於大多數開發者來說,在遺留程式碼基礎上開發是日常工作的一部分,畢竟從頭開始建立全新系統的機會不是很多。架構師、《漫談設計模式》作者劉濟華結合自身的實際經歷分享瞭如何在遺留程式碼基礎上開發的經驗。

  劉濟華首先指出,大多數系統是構建在之前的遺留系統之上的,在開始,很難把遺留系統直接丟棄,特別是一些業務邏輯非常複雜的金融電信系統。 這些程式碼往往有如下特點:

  • 舊的程式語言開發低效。
  • 程式碼冗繁,質量差。
  • 新增新的功能和修改錯誤(Bugs)的週期時間長而痛苦。
  • 這些程式碼沒有單元測試,甚至沒有功能測試、冒煙測試、迴歸測試。
  • 無法交接這些程式碼,因為寫程式碼的這些人很多已經離職。
  • 維護這些程式碼代價高,大家心驚肉跳,特別是系統遇見特殊情況(節假日,高峰訪問期等),無法安寧。

  但是這些程式碼能夠完成當時的功能,直接拋棄這些程式碼,重新開發將會耗費很大的資源,且不一定成功,如果新的需求不斷變化,往往沒有時間來重新開發這些程式碼。而這些遺留程式碼的功能沒有完善的文件說明,甚至沒有。 在此現狀下,如何改善這些程式碼,將是考驗程式設計師和一個團隊的智慧。

  接著,劉濟華分析了對於遺留程式碼取捨的親身經歷。

  • 具有效能瓶頸的遺留系統——曾經遇到過一個應用服務,是C語言寫的,周圍其他系統都是採用Java開發,與此係統的互動都是採用非標準的協議完成,而且此係統處於比較核心的位置,但是維護非常複雜,不穩定,訪問壓力大是經常當機,無法水平擴充套件,只能提高硬體裝置水平等方式考慮。
    在原有協議基礎上開發,使其具有水平擴充套件能力,代價和開發一套標準協議的實現沒有任何區別,往往會帶了協議不夠完善所產生的問題。於是,我們為其開發新的標準協議,WS,MQ等等,然後在標準協議上負載均衡實施水平擴充套件,非常方便。
    隨著後來的發展,此遺留程式碼也慢慢被新開發系統取代,期間經歷了新系統和舊系統同時存在,此時新系統未完全具有舊系統的全部功能,這部分功能還是使用舊系統完成,只不過在原有均衡負載層多了層查詢和分配的,後來到舊系統完全取代。此過渡還算平順。
  • 功能性改造型系統——大多數就是這種系統,保留的話,程式碼極其複雜,維護麻煩,丟棄的話,無法一夜之間寫出新的系統。曾經接手了一個開發失敗的專案,包括程式碼和文件都未完善,如果重新來過,終究不划算,後來在此係統上進行改造,特別是花了大量時間寫單元測試,保證程式碼測試覆蓋率極高,這樣一邊熟悉程式碼,一邊重構程式碼,系統的健壯性發生根本改變,前提是有時間。這只是特例。很多時候遇見的系統,同樣測試程式碼很少,在新增新的功能和修復錯誤(Bugs)時,為這些能夠接觸到的程式碼完善測試,新程式碼必須測試覆蓋率必須很高,經過4個月,,此係統程式碼覆蓋率已經達到50%以上。以後的迭代開發越來越快。

  那麼如何在在遺留程式碼上程式設計呢?劉濟華覺得首先要找到程式碼修改點:

遺留系統程式碼往往測試少,或者沒有,導致軟體開發者對軟體釋出沒有信心。但是為所有的遺留程式碼寫單元測試,初始代價非常高,在新增一個很小的功能時,並沒有時間大動干戈。

  如何找切入點呢?劉濟華總結了幾種情況:

  • 修改一處程式碼即可,這個時候非常簡單,修改程式碼處即為切入點,找到這處修改即可,為此處程式碼寫完善的單元測試程式碼,特別是對於輸入條件和測試條件儘量能夠完整測試。
  • 修改多處程式碼,位置分散,並且修改程式碼如果有多種方案,我們找出最少修改程式碼的地方,而不是最佳的修改方式,很多時候,此時最佳的程式碼修改會修改很多程式碼,導致測試程式碼無法一下子完善,另外,此時認為的最佳方案隨著時間的推移,或許又是糟糕的程式碼,所以沒有必要花費更多的精力在上面,當然也可以選擇比較中庸的方式。

  在修改時需要一些技巧,其中包括:

  • 找測試方便、改動較小的方式來修改遺留程式碼。
  • 重構在一個類中那些重複的方法,並且保證其健壯性。
  • 為依賴的具體類提取新的介面,並使用注入依賴技術,使得測試更加容易,不管是使用Mock tool還是自己編寫Mock物件,都會非常容易測試。
  • 儘量使測試的範圍縮小在受修改影響的類中,對類中的改動進行全面測試。保證每處修改完全測試,保證測試類減少。
  • 類之間互動的程式碼重構,如果這些互動僅在修改的程式碼之中,只要保證修改的程式碼完全測試即可。而對於那些可能影響此時其他不需要進行修改程式碼的類,可以先放下,為其建立新的方法,在此次修改和以後修改中,使用和重構新的方法。對於老的方法,等到以後程式碼覆蓋率提高,能夠覆蓋所有此類互動方法的程式碼時,重構此方法,這是你會發現,修改很簡單,並且如果修改錯誤,或者不能處理極端的邏輯,也會和容易找出問題所在。
  • 努力汲取業務邏輯知識。
  • 《修改程式碼的藝術》(Michael Feathers 著)建議找到切入點(Inflection Point),往往我們找的點很多,每一次修改都可能不一樣,為此花很多代價找尋,還不如直接進入修改,找出最佳的修改方式避免程式碼過度重構和修改,減少影響,這才是有有實踐價值和有意義的。

  如何保證質量呢?劉濟華建議:

  • 儘可能讓一切自動化——單元測試自動化是最基本要求,儘可能讓一切測試變得自動化,不管是單元測試,還是功能測試,還是壓力測試、冒煙測試、迴歸測試。釋出自動化也是非常重要的。
  • 為專案加入冒煙測試和迴歸測試。逐漸保證程式碼質量。
  • 堅持可控變化、逐漸滲透的原則,保持系統穩步的朝健壯的方向進行。

相關文章