只懂 Git 如何成為架構(gòu)磚家?從代碼的物理分析說起
物理分析這一詞,來源于我同事 @NoaLand 所推薦的《大規(guī)模 C++ 程序設(shè)計(jì)》一書中所介紹的物理設(shè)計(jì)。
物理設(shè)計(jì)集成于研究系統(tǒng)中的物理實(shí)體,及它們之間如何相互關(guān)聯(lián)。邏輯設(shè)計(jì)只研究體系結(jié)構(gòu)(架構(gòu))問題,物理設(shè)計(jì)研究組織問題。
在粗粗了這本書的一些概念之后,我對整體的物理設(shè)計(jì)思路有更深入的了解。于是,在結(jié)合了《系統(tǒng)重構(gòu)與遷移指南》一書中引入的『四級重構(gòu)』,重新論證了我先前的一個(gè)想法:并不需要成為 xx 語言的熟練開發(fā)者,我也能分析這個(gè)語言的系統(tǒng)設(shè)計(jì)得是否合理?(PS:這是建立在我已經(jīng)熟練使用多門語言 Copy/Paste 的前提下。)
于是乎,只需要學(xué)會對物理設(shè)計(jì)進(jìn)行分析,就能成為架構(gòu)上的磚家 —— 對于這部分的分析,是個(gè)程序員都會做。
而一系列的理論建立在幾個(gè)基本的前提之下:
- 代碼組件方式使用文件系統(tǒng)的方式組件。即包和組件使用文件夾管理等。
- 項(xiàng)目使用的是 Git,絕大多數(shù)的 Git 修改都是自然發(fā)生的,即技術(shù)需求和業(yè)務(wù)需求。
- 項(xiàng)目所使用的是主流的企業(yè)開發(fā)語言。如 Java、Golang、JavaScript/TypeScript、C#、C++ 等,而不是 Haskell 等。
這里,我們使用的分析工具是 Inherd 開源小組開發(fā)的研發(fā)效能分析工具 Coco,GitHub:https://github.com/inherd/coco。
文中使用的是 Redis 案例在線版本見:https://inherd.org/cases/redis/
“物理”架構(gòu)設(shè)計(jì)
我們所熟知的包,可以定義為:一個(gè)包就是被組織成一個(gè)物理內(nèi)聚單位的組件集合。而包的呈現(xiàn)形式便是文件夾,其中的一個(gè)個(gè)物理單元就是文件。通過對文件的修改的監(jiān)測,我們可以知道文件夾的變化,進(jìn)而觀測到整個(gè)包的變化。
通過這些物理上的變化,我們可以知道一個(gè)包是否是穩(wěn)定的,從它的大小,我們還能知道整體的設(shè)計(jì)是否合理。如下是 自 2020.3.1 號起, Redis 中不同模塊的源碼變化情況:
Redis Changes
(PS:該圖是交互式的網(wǎng)頁。左側(cè)的五彩斑斕部分是 src/,也就是主要源碼,右側(cè)是依賴的了模塊,上方是測試模塊的變化。)
從上圖中:
觀測頻繁修改模塊??梢郧逦乜吹侥膫€(gè)模塊變化較多。對于業(yè)務(wù)代碼來說,我們則可以通過時(shí)間軸的大小,來觀測不同時(shí)代段的修改。
了解包的大小。如圖中的 redis-cli.c:41,其中的 41 是自 2020.3.1 起的修改次數(shù),hover 在上面之后,可以知道這個(gè)文件的行數(shù)為 7012 行。
根據(jù)我們《系統(tǒng)重構(gòu)與遷移指南》定義的高引用、高修改的關(guān)系:
高引用-高修改
我們也可以建議一個(gè)輕微地模型(不會那么準(zhǔn)確),來證明一個(gè)長行數(shù) + 頻繁修改這是一個(gè)非常不穩(wěn)定、容易出錯的包。而在業(yè)務(wù)場景之下,如果我們實(shí)現(xiàn)的一個(gè)功能,為于 A 業(yè)務(wù)之下,但是一直在修改 B 業(yè)務(wù),那么說明引用是不正確的,存在一定的耦合度。
變更頻率
變更頻率是一個(gè)非常有意思的指標(biāo),從版本管理工具中,我們可以獲得歷史上發(fā)生的一些變化。從結(jié)論上來說,我們常知道的一些事實(shí)有:
- 隨著代碼行數(shù)的上升,新增代碼的占比會越來越少,修改成本也越來越高,因此提交量會呈一定的下降趨勢。
- 軟件開發(fā)是周期性的活動。修改頻率與軟件發(fā)布成正比例關(guān)系。
下圖展示的是 Redis 的所有提交與時(shí)間的關(guān)系:
Redis Commit Contributions
從圖上來看,在 2014 ~ 2015 之前發(fā)生了大量的代碼提交。與它與后面的發(fā)布頻率,做一個(gè)對比,我們就會發(fā)現(xiàn)這一段時(shí)間發(fā)布了大量的新版本。從這些現(xiàn)象來看,它可能意味著:
- 在這段時(shí)間引入了大量的功能。
- 因?yàn)檫^多的功能,并因此引入了大量的 bug,所以需要更多地版本發(fā)布。
除此,另外一個(gè)不是那么有意思的指標(biāo)就是行數(shù)上的變化:
Redis Line History
從圖中我們可以看到在 2011 ~ 2012 這個(gè)時(shí)間點(diǎn)上,代碼量突然發(fā)生了劇烈的變化。其中原因,我想就是因?yàn)樗麄兯捎玫氖?feature branche 的機(jī)制。即,功能在開發(fā)完成后,才會合并到主分支。
從下面的發(fā)布頻率中,我們也可以看到這個(gè)變化的趨勢。
發(fā)布頻率與部署
從 Git 中想看到發(fā)布頻率相關(guān)的內(nèi)容,只能從以下兩部分:
- 分支??梢哉故痉种У氖褂们闆r,以及不同分支的變化。
- Git Tag。展示軟件的發(fā)布頻率與時(shí)間等的關(guān)系。
如下是 Redis 的分支歷史:
Redis Branches
從圖中,我們可以清晰地看到 Redis 的不同特性地開發(fā),如 arm,如 acl-log。除此,還有不同版本的維護(hù)情況,如 2.8 的修改在 3.0 之后。
同樣的,因?yàn)?Redis 采用的是標(biāo)準(zhǔn)的 Git 實(shí)踐來發(fā)布軟件。所以,從 2019 年的 tags,我們可以看到軟件的整體發(fā)布情況:
Redis Tags
咦,從上圖來看,這個(gè)是 6.0 是不是來得非???。沒有 5.1.x 就直接 666 了。
學(xué)習(xí)成本與知識管理
軟件開發(fā)是一個(gè)知識生產(chǎn)和消費(fèi)的過程。—— 《軟件開發(fā)管理為什么這么難》
在一個(gè)項(xiàng)目的不同時(shí)期(技術(shù)準(zhǔn)備、業(yè)務(wù)回補(bǔ)、成長優(yōu)化、架構(gòu)演進(jìn)),其對于不同級別的開發(fā)人員的難度都是不一樣的。這一點(diǎn)從理論上來講,我們可以從分析其的提交資料,來分析它的學(xué)習(xí)成本。開發(fā)人員的提交量會隨著在項(xiàng)目的年限逐漸變多,直到趨于穩(wěn)定。
于是,我們嘗試從 Redis 項(xiàng)目里建立這個(gè)模型:
Redis Curve
然后失敗了。后來,發(fā)現(xiàn)這個(gè)模式并不適合于開源項(xiàng)目。
與商業(yè)軟件相比,開源軟件的更加動態(tài),團(tuán)隊(duì)的生命周期很少超過六個(gè)月,并且常常會以各種方式重組。——《軟件之道:軟件開發(fā)爭議問題剖析》
但是,我們相信它對于常規(guī)的軟件開發(fā)團(tuán)隊(duì)是適用的。
隨后,我們再正視了一下這個(gè)問題,重新考量了適合于開源項(xiàng)目的模型 —— 通過人員在項(xiàng)目的提交時(shí)間,來看一個(gè)項(xiàng)目是否穩(wěn)定,知識傳播是否靠譜。
如下是 Redis 項(xiàng)目中,開發(fā)人員的第一次提交時(shí)間和最后一次開發(fā)時(shí)間產(chǎn)生的 timeline:
Redis Members
它從側(cè)面反應(yīng)了,開源項(xiàng)目的團(tuán)隊(duì)模式,只有少數(shù)的開發(fā)人員。對于商業(yè)軟件來說,如果 timeline 如上的話,那么這個(gè)軟件仍然能夠開發(fā)下去。但是,如果核心開發(fā)人員離開團(tuán)隊(duì),項(xiàng)目將非常不穩(wěn)定,那么這個(gè)軟件將充斥著大量未知的 bug。
其它
這樣一看,Coco 是不是降低了架構(gòu)分析的門檻。歡迎試用 Coco,可以從 GitHub 直接下載:https://github.com/inherd/coco/releases
文中說的一些分析內(nèi)容,已經(jīng)在我之前的另外一分析工具 Coca 中引入過。但是,受限于語法分析的成本,所以在 Coco 中采用了輕量級的分析方式。我們會在后續(xù)的文章中,介紹更多想多的實(shí)現(xiàn)方式。你也可以通過添加微信號 phodal02 (注明 Inherd),參與到相關(guān)的討論中。
文中使用的是 Redis 案例在線版本見:https://inherd.org/cases/redis/
相關(guān)資源:
《Introducing the Polyglot Code Explorer》
《Your code as a crime scene》
本文轉(zhuǎn)載自微信公眾號「phodal」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系phodal公眾號。