如何快速分析大型系統(tǒng)架構(gòu)?
本文轉(zhuǎn)載自微信公眾號(hào)「phodal」,作者phodal 。轉(zhuǎn)載本文請(qǐng)聯(lián)系phodal公眾號(hào)。
最近,因?yàn)楣卷?xiàng)目的原因,對(duì)一個(gè)大型的系統(tǒng)做了一個(gè)簡(jiǎn)要的架構(gòu)分析。由于,時(shí)間上的限制,所以在這里我也只能做一個(gè)快速的分析,并沒(méi)有其它的可能性。
太長(zhǎng)不看版步驟:
- clone 項(xiàng)目的代碼,以及相關(guān)的依賴
- 嘗試編譯系統(tǒng)
- 借助目錄 + 編輯器進(jìn)行初步分析
- 借助工具進(jìn)行可視化分析
- 配置 IDE,進(jìn)行源碼分析
- 繪制架構(gòu)圖
- 從用戶旅程驗(yàn)證架構(gòu)正確性
- 總結(jié)輸出
- 回溯版本,進(jìn)一步驗(yàn)證
PS:這里所針對(duì)的情況是,沒(méi)有現(xiàn)有架構(gòu)圖的情況。如果已經(jīng)有現(xiàn)成的架構(gòu),那么它的步驟應(yīng)該是不一樣的。依我之間的經(jīng)驗(yàn)來(lái)看,它應(yīng)該是這樣的:
- 尋找架構(gòu)圖
- 尋找相關(guān)的閱讀代碼文檔、日記
- 其它同上
0. clone
多數(shù)情況下,把遠(yuǎn)程的代碼 clone 到本地,是一件非常簡(jiǎn)單的事情。但是,并非所有的情況都是如此,因?yàn)閷?duì)一個(gè)大型的系統(tǒng)來(lái)說(shuō),我們要面對(duì)著這么一些情況:
- 代碼庫(kù)過(guò)多
- 代碼量過(guò)大
于是,在我所需要分析的這個(gè)系統(tǒng)里,它采用了 Google 的多倉(cāng)庫(kù)管理工具 Repo。這樣就從一定程度上解決代碼庫(kù)過(guò)多的問(wèn)題——對(duì)于我們來(lái)說(shuō),我們只需要執(zhí)行一個(gè) repo sync,它就可以幫助我們把所有的代碼 clone 下來(lái)。而后,我們只需要等待幾小時(shí),或者幾天,就可以下到我們的代碼庫(kù)了。
1. 嘗試編譯系統(tǒng)
有了代碼之后,我們就可以嘗試按文檔的步驟來(lái)構(gòu)建應(yīng)用。期間,我們還需要解決一些工具上的問(wèn)題,又或者是按官方的 issue 來(lái)處理一些異常情況。
與此同時(shí),你還可能會(huì)遇到我在這個(gè)項(xiàng)目上遇到的問(wèn)題:當(dāng)前版本是無(wú)法成功構(gòu)建的。
于是,我還需要重新花一天時(shí)間,再找到某一個(gè)特定版本的代碼……。
2. 借助目錄 + 編輯器進(jìn)行初步分析
與此同時(shí),在我們進(jìn)行編譯的時(shí)候,還可以同時(shí)簡(jiǎn)單地對(duì)項(xiàng)目進(jìn)行分析:
- 目錄結(jié)構(gòu)分析。通過(guò)查看目錄名稱和目錄結(jié)構(gòu),分析項(xiàng)目的組成關(guān)系。
- 代碼簡(jiǎn)單分析。嗯,從一個(gè)入口點(diǎn),一步步查看調(diào)用關(guān)系等。
之所以,我們還不能用 IDE 進(jìn)行分析的一個(gè)原因是:對(duì)于這樣的一個(gè)系統(tǒng)來(lái)說(shuō),IDE 是一個(gè)龐大的吃內(nèi)存怪物。而在當(dāng)前時(shí)刻,我們還在嘗試構(gòu)建這個(gè)系統(tǒng),它不僅吃內(nèi)存,還吃 CPU。甚至于,你的電腦還會(huì)因此而卡住。
3. 工具可視化
進(jìn)一步地考慮到了項(xiàng)目的代碼量的問(wèn)題,簡(jiǎn)單地靠人力分析起來(lái)比較困難。我們就需要借助于一些工具來(lái)對(duì)代碼進(jìn)行分析。
由于這是一個(gè) Java 項(xiàng)目,我就可以用我之前寫(xiě)的系統(tǒng)分析工具:Coca。用它來(lái)繪制基本的架構(gòu)圖:
Package Arch Demo
還有某一個(gè)方法或者是類的上下調(diào)用關(guān)系:
call
4. 配置 IDE,進(jìn)行源碼分析
在騰出了足夠的 CPU + 內(nèi)存資源之后,我們就可以輕松愉快地打開(kāi) IDE,進(jìn)行源碼分析。于是,很快地,我就需要等待 IDE 把代碼索引完。
好了,IDE 卡住了。
模塊分析
接著,我嘗試了另外一種可能性,打開(kāi)其中的某一個(gè)工程查看源碼,但是很快地我發(fā)現(xiàn)了:缺少依賴。因?yàn)榭傮w的構(gòu)建失敗,導(dǎo)致了總工程的一些依賴無(wú)法構(gòu)建成功。
于是乎,我嘗試了另外一種可能性:提取生產(chǎn)環(huán)境的依賴。畢竟,我所需要的依賴是一些 jar 包,而 jar 包會(huì)伴隨著系統(tǒng)一起分發(fā)。這樣一來(lái),我就能從發(fā)布包中復(fù)制依賴到工程中使用,然后愉快地繼續(xù)閱讀代碼了 —— 順便地也能從依賴分析項(xiàng)目的情況。
工程內(nèi)依賴分析
嗯,對(duì)于某些模塊來(lái)說(shuō),它的產(chǎn)出是一個(gè) jar 包,那么我們不一定需要閱讀它地源碼。只需要理清單個(gè)模塊的構(gòu)建產(chǎn)物,以及它的作用即可。
5. 繪制架構(gòu)圖
嗯,有了上面的基礎(chǔ)之后,我們就可以繪制架構(gòu)圖了。
暫時(shí)沒(méi)啥好的工具推薦,Google Slides、Sketch 這一類的都可以。
如果是調(diào)用關(guān)系的話,可以用 Graphviz 來(lái)繪制。只是呢,我已經(jīng)用 Coca 來(lái)自動(dòng)化繪制這個(gè)依賴關(guān)系了。哈哈
6. 用戶旅程驗(yàn)證
我們閱讀代碼時(shí),都是從入口開(kāi)始驗(yàn)證。如基于 Spring 的微服務(wù)項(xiàng)目,都是從 API 注解作為入口點(diǎn),一步步分析這個(gè)系統(tǒng)的架構(gòu);如 Angular 開(kāi)發(fā)的前端應(yīng)用,是從 main.ts 開(kāi)始的。如 IDEA 插件,是從 plugin.xml 開(kāi)始的,從 Action 綁定用戶行為。
以類似的方式,我們就可以在不能調(diào)試的情況下,進(jìn)一步驗(yàn)證架構(gòu)的提煉是否合理。
7. 回溯版本,重復(fù)
考慮到我使用的版本是不能成功編譯地版本,所以又花了點(diǎn)時(shí)間再下一個(gè)舊版本的系統(tǒng),以驗(yàn)證部分關(guān)系是否是正確的。
畢竟只有成功編譯地版本,才是正常的版本。
8. 總結(jié)輸出
這些相關(guān)的產(chǎn)物可以有:
- 過(guò)程日志
- 問(wèn)題總結(jié)
- 架構(gòu)圖
- 仿制的 MVP demo
在這里,我們還是強(qiáng)調(diào)一下最后一個(gè),我經(jīng)常拿這種方式來(lái)創(chuàng)造輪子。
人生苦短,我有 Coca。
http://github.com/phodal/coca