代碼分析與自動(dòng)化重構(gòu)工具集:Modernizing
遺留系統(tǒng)的現(xiàn)代化演進(jìn)是一門(mén)藝術(shù)。
Why 開(kāi)源 + 遺留系統(tǒng)現(xiàn)代化工具
在日常的軟件開(kāi)發(fā)里,我們經(jīng)常會(huì)遇到一系列的問(wèn)題,諸如于:
- 如何解決人類(lèi)智商不夠的問(wèn)題?模式、原則和工具
- 誰(shuí)應(yīng)該去解決代碼的問(wèn)題?代碼
- ……
應(yīng)對(duì)于這些問(wèn)題,其中的一個(gè)解決方案就是: 自動(dòng)化的工具 ,有些人喜歡稱(chēng)之為 器 。支撐這些工具的便是一系列的 原則 與 模式 ,將它們?nèi)谌氲焦ぞ咧?。另外一個(gè)解決人成長(zhǎng)的方案就是:元元(meta-meta),這是另外一個(gè)故事。
遺留系統(tǒng)是常態(tài)。多數(shù)時(shí)候,我們所遇到的系統(tǒng)里多數(shù)是遺留系統(tǒng),來(lái)到一個(gè)新項(xiàng)目時(shí),可能就需要對(duì)他們快速的分析,以提供洞見(jiàn) —— 寫(xiě) PPT 匯報(bào)。所以,在過(guò)去的幾年里,咨詢(xún)團(tuán)隊(duì)也沉淀了一系列的遺留系統(tǒng)分析和重構(gòu)的工具,比如新哥的 Tequila、正在開(kāi)源的架構(gòu)分析和守護(hù)工具 ArchGuard 等等。除此,在有些重構(gòu)項(xiàng)目里,還要編寫(xiě)定制的工具來(lái)進(jìn)行分析。
技術(shù)熱情發(fā)電。主要的挑戰(zhàn)是,我們需要拿自己的業(yè)余時(shí)間來(lái)完善工具。
既然要用自己的時(shí)間來(lái)開(kāi)發(fā),還和項(xiàng)目沒(méi)有關(guān)系,這種 用愛(ài)發(fā)電 的事情,用開(kāi)源的方式最合適了。
我們需要怎樣的工具?
從對(duì)于使用工具的結(jié)果來(lái)看,我們需要這個(gè)現(xiàn)代化工具是:
特定壞味道。不同的開(kāi)發(fā)團(tuán)隊(duì)會(huì)有不同的壞味道,有些壞味道是無(wú)法由 Sonarqube 這樣的工具識(shí)別的。
自動(dòng)化重構(gòu)?;谝阎膲奈兜?,對(duì)應(yīng)的代碼位置信息,對(duì)代碼進(jìn)行自動(dòng)化重構(gòu)。
- 可視化驅(qū)動(dòng)??焖偕身?xiàng)目的分析結(jié)果,并展示出來(lái)給開(kāi)發(fā)人員了解現(xiàn)狀,還有編寫(xiě) PPT。
- 必要的交互性。用于在重構(gòu)的過(guò)程中,尋找合適的切入點(diǎn)。
- 定制化開(kāi)發(fā)。
- 適當(dāng)?shù)恼Z(yǔ)法精準(zhǔn)度。更高的語(yǔ)法精準(zhǔn)度,意味著更高的開(kāi)發(fā)成本,需要有針對(duì)地平衡它們。
- 多平臺(tái)。我們用的是 macOS,而多數(shù)時(shí)候,客戶(hù)使用的是 Windows。
如何開(kāi)發(fā)這樣的工具?
這里定義的遺留系統(tǒng)現(xiàn)代化工具包含了這么幾部分:語(yǔ)法分析、結(jié)果及可視化、自動(dòng)化重構(gòu)、架構(gòu)守護(hù)。
語(yǔ)法分析
對(duì)代碼進(jìn)行語(yǔ)法分析,生成特定的語(yǔ)言的數(shù)據(jù)結(jié)構(gòu)。常用的工具有:Antlr、Ctags、TreeSitter、Doxygen、CodeQuery 等。一個(gè)大致的對(duì)比(拍腦袋訂的)如下表所示:
結(jié)果及可視化
通常來(lái)說(shuō),我們會(huì)出于以下的一些情況,來(lái)對(duì)遺留系統(tǒng)進(jìn)行可視化:
- 數(shù)值化。如針對(duì)于特定的 smell 進(jìn)行自動(dòng)化重構(gòu),類(lèi)似于 Sonarqube,常見(jiàn)的模式和原則源自于《重構(gòu)》一書(shū)。在 Coca 里,還引入了在一些論文里看到了測(cè)試的 bad smell,諸如于沒(méi)有斷言的測(cè)試等。
- 可視化依賴(lài)。如針對(duì)于代碼中的類(lèi)、包等的依賴(lài)情況進(jìn)行可視化,主要用于分析分層架構(gòu)等。常用的工具有:PlantUML、Graphviz、D3.js、Echarts 等。
- 代碼屬性可視化。如針對(duì)于文件的修改頻率、大小等屬性進(jìn)行可視化,可以獲取諸如于單位時(shí)間內(nèi)的文件變化頻率。一個(gè)文件經(jīng)常修改,還大量被引用,那說(shuō)明它是一個(gè)不穩(wěn)定的類(lèi)、文件,除了業(yè)務(wù)變化,最有可能就是設(shè)計(jì)不合理。
- 其它。
自動(dòng)化重構(gòu)
這一步是可選的,它取決于我們的場(chǎng)景。通常來(lái)說(shuō),編寫(xiě)這樣的功能主要彌補(bǔ)是現(xiàn)代化的 IDE 無(wú)法完成的工作,諸如于:
- 多代碼庫(kù)間的未使用類(lèi)刪除。
- 多代碼庫(kù)間的聚類(lèi)。
- 針對(duì)于 CSS 顏色的重構(gòu)。
架構(gòu)守護(hù)
編寫(xiě)架構(gòu)的守護(hù)規(guī)則,以對(duì)于系統(tǒng)的架構(gòu)進(jìn)行守護(hù),用的工具有:ArchUnit、ArchGuard 等。在參考了 ArchUnit 的語(yǔ)法之后,我們也設(shè)計(jì)了一個(gè)多語(yǔ)言的架構(gòu)守護(hù)工具:Guarding。
在開(kāi)發(fā)這些工具的過(guò)程中,它們也不斷地 push 著我進(jìn)一步學(xué)習(xí)語(yǔ)言背后的東西,如編譯原理(語(yǔ)言的前端部分),理解構(gòu)建系統(tǒng)(build system)等。
遺留系統(tǒng)現(xiàn)代化工具集
為了更有針對(duì)性地對(duì)遺留系統(tǒng)進(jìn)行現(xiàn)代化,最近我們創(chuàng)建了一個(gè)新的組織:Modernizing,集合了先前開(kāi)發(fā)的一系列工具。并創(chuàng)建了:awesome-modernization 用于對(duì)其它的一系列相關(guān)的工具進(jìn)行收集。
在 Modernizing 里,針對(duì)于單個(gè)編程語(yǔ)言的工具有:
- 針對(duì)于 Java 語(yǔ)言的系統(tǒng)重構(gòu)、系統(tǒng)遷移和系統(tǒng)分析的工具: Coca ,Go 語(yǔ)言,GitHub stars:691。Coca 是一個(gè)“全功能”的重構(gòu)工具,基于 Antlr 進(jìn)行語(yǔ)法分析的,除了常規(guī)的可視化、調(diào)用分析,還可以進(jìn)行自動(dòng)化重構(gòu)。Coca 一名的由來(lái)是:對(duì)標(biāo)新哥寫(xiě)的 Tequila —— 龍舌蘭酒 vs 快樂(lè)水。
- 針對(duì)于 CSS/LESS/CSS 的分析和自動(dòng)化重構(gòu)工具: Lemonj ,TypeScript 語(yǔ)言,GitHub stars:128。當(dāng)時(shí)設(shè)計(jì)的主要目的是:用來(lái)對(duì) CSS 中的顏色進(jìn)行提取,基于 Antlr 的語(yǔ)法樹(shù)分析,可以用于進(jìn)行自動(dòng)化的重構(gòu)。
- 針對(duì)于 MySQL 代碼進(jìn)行自動(dòng)化分析,并從中構(gòu)建中 UML,并生成其關(guān)系的: SQLing ,Go 語(yǔ)言,使用 PingCap 的 SQL 解析器解析。當(dāng)然了,還有一個(gè)初始化的針對(duì)于 PL/SQL 的版本:pling。
- 適用于 Ant 轉(zhuǎn) Maven 的半自動(dòng)化工具: Merry ,Go 語(yǔ)言 + Antlr。
- 前端規(guī)范化改造工具: Clij ,用于一鍵添加 eslint、husky、lint-staged 等,TypeScript 語(yǔ)言。
針對(duì)于多語(yǔ)言的工具,我們有:
- 基于 Antlr 的多語(yǔ)言的語(yǔ)言模型分析工具: Chapi ,Kotlin 語(yǔ)言。其設(shè)計(jì)的初衷是用于生成 Coca 相同的數(shù)據(jù)結(jié)構(gòu),以接入更多的可視化工具。在語(yǔ)法分析上,采用的是 Antlr 進(jìn)行分析。
- 基于 Doxygen 的多語(yǔ)言分析和可視化工具:Go mod 版本的新哥的 Tequila 。其中,還有一系列的迷之代碼,需要重構(gòu)掉。
- 基于 Ctags 的多語(yǔ)言模型分析和可視化工具: Modeling ,Rust 語(yǔ)言。分析源碼,并生成基于模型的可視化依賴(lài)。
- 基于 TreeSitter 的多語(yǔ)言架構(gòu)守護(hù)工具: Guarding ,Rust 語(yǔ)言。通過(guò)自制的 DSL,來(lái)對(duì)系統(tǒng)架構(gòu)進(jìn)行守護(hù)。
除此,還有一個(gè)在 Inherd 開(kāi)源小組下開(kāi)源的:Coco,它主要是通過(guò)代碼的物理屬性:修改頻率 + 目錄 + 行數(shù)來(lái)分析系統(tǒng)的工具。以及現(xiàn)在緊鑼密鼓開(kāi)源中的 ArchGuard。
我們使用一系列不同的語(yǔ)言和工具來(lái)開(kāi)發(fā)這些軟件,因?yàn)椴煌膱?chǎng)景之下,都會(huì)有不同的選擇。
下一步?
現(xiàn)有的工具都是分散的,不同工具之前的數(shù)據(jù)格式不盡相同,缺乏統(tǒng)一的數(shù)據(jù)格式。在輸出格式不統(tǒng)一時(shí),我們就難以進(jìn)行標(biāo)準(zhǔn)的可視化,諸如于我們正在構(gòu)建 codecity 用于在元宇宙里,對(duì)遺留系統(tǒng)進(jìn)行可視化,又或者是正在從 ArchGuard 中拆分的前端可視化部分,以用于復(fù)用。理想的情況下,它應(yīng)該像是一個(gè) pipeline 架構(gòu)的系統(tǒng),由一系列的 pipe 和 filter 所構(gòu)成。
歡迎訪(fǎng)問(wèn)我們的 GitHub: https://github.com/modernizing