如何管理和優化日益增長的代碼復雜度?
隨著時間的推移,軟件項目會變得越來越大,項目中組件之間的依賴關系也會變得越來越錯綜復雜,項目的維護也會變得越來越困難。
Plumbr(Java內存泄露檢測器)開發團隊的一篇博文揭示他們這個項目在開發過程中,其代碼復雜性是如何演變的。
本文中的這些代碼依賴圖是該團隊在項目開發過程中使用Structure 101來 生成的。通過Structure,開發者可以定義一個規則來約束代碼之間的交互和依賴關系,從而簡化開發和重構過程中的代碼復雜度管理。但在Plumbr 項目一開始,并沒有使用Structure,只使用了其中的Restructure產品來可視化項目中的依賴。但在后面項目越做越大時,團隊才開始考慮使 用Structure。
Restructure使用如下兩個指標來表示代碼的質量:
- Tangle(混亂度):用來表示代碼構件(比如包、類)之間的關系是否錯綜復雜
- Fat(肥胖度):用于表示單獨的類、包是否龐大且雜亂
嚴格來說,并不是Tangle和Fat數值小就意味著你的代碼庫比較好。但是這兩個指標確實能為你的代碼優化工作帶來一些幫助,比如規模較小的單個代碼片 (Fat數值小)更容易讓人理解,依賴關系少(Tangle數值小)的代碼更具可預測性,這樣的代碼中的bug就會更少,代碼也更容易維護。
下面就來看看Plumbr項目代碼的復雜性的演變。
故事始于2011年初,那時剛開始創建代碼庫。從下面的截圖中可以看到,代碼的Tangle數非常低(圖左上角色譜中的小黑點),可以說這為將來的開發工作打下了一個堅實的基礎。但實際情況是,項目團隊僅僅只寫了幾千行源代碼,還沒來得及寫更多東西。
但是只過了6個月,就呈現出了不同的畫面。如下圖所示,Fat數依然很低,但是依賴關系已經開始變得混亂(看小黑點的縱坐標軸)。
又過了6個月,可以看到項目代碼Fat數依然很低,Tangle數依然很高。但是你可以看到一些包(allocation、io、lifecycle)現在已經從混亂的代碼庫中獨立了出來。其實,該團隊在這個時期的后段使用了Structure 101來管理代碼。
又過了半年時間,事情似乎走向了極端。現在除了依賴關系異常混亂外,代碼的Fat情況也相當嚴重。這時項目團隊開始全面使用Structure 101產品來分析下面這張圖片,并問自己一些有實際意義的問題,比如:
- 為什么report代碼要依賴一個引用包?
- 為什么在文件系統工具和日志包之間有這么一個強周期性依賴?
當然,即使沒有Structure 101這個工具,也應該問自己一些類似的問題。但不可否認,該工具對問題進行了可視化,對于優化代碼有很大的幫助。
#p#
發現問題后,項目團隊就開始采取措施進行優化。下面這張圖片大約是半年前的,可以看到,所有添加的新代碼已經變得整潔,比如同級組件(fs、http等)之間的依賴關系現在已經得到了改善。
下面這張圖片是一周前的。雖然代碼庫比半年前增長了25%,但是Tangle數已經成功地從39,000減少到了16,000,代碼變得更加整潔、結構更加自然了。另外,項目團隊的開發水平也有了一定的提高。
結論
項目代碼復雜性的管理要貫穿項目始終,這樣到項目后期,維護起來也不會特別困難。或者你可以制定一些依賴規則,然后在開發過程中強制執行。
這個故事是一個很好的樣本,展示了一個小團隊如何在一個相對短的時間內創建一個混亂的代碼庫。你也可以設想一下,如果一個10人開發團隊開發一個預期壽命為10年的項目,最終的項目依賴關系圖會是什么樣的呢?