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