利用依賴結(jié)構(gòu)矩陣管理架構(gòu)債務(wù)
技術(shù)債務(wù)(Technical Debt)是軟件開發(fā)的熱門話題,隨著時(shí)間推移,源代碼逐漸增多,技術(shù)債務(wù)也變得越來越復(fù)雜。有很多分析技術(shù)債務(wù)的工具,基本上都專注于代碼質(zhì)量。架構(gòu)債務(wù)是技術(shù)債務(wù)的一部分,但由于沒有像技術(shù)債務(wù)那樣的自動化工具,因此并不容易確定。
在確定架構(gòu)債務(wù)時(shí),應(yīng)研究與源代碼耦合的"架構(gòu)反模式"。以下是需要確定和消除的常見架構(gòu)反模式:
- 不穩(wěn)定接口:這些接口通常是系統(tǒng)的應(yīng)用程序接口或入口點(diǎn),有許多依賴組件,接口的微小改動都會讓所有依賴組件頭疼不已。
- 違反模塊化原則:軟件系統(tǒng)應(yīng)采用模塊化架構(gòu)。這意味著可變更組件應(yīng)架構(gòu)在同一模塊中,以避免模塊間的依賴。如果一個(gè)模塊的變化對其他模塊產(chǎn)生了巨大影響,就應(yīng)該研究這一不穩(wěn)定的根本原因。
- 不健康的繼承:當(dāng)超類依賴于子類或調(diào)用者類依賴于超類和子類實(shí)例時(shí),就會出現(xiàn)這種情況。
- 循環(huán)依賴:例如,當(dāng)組件 A 依賴于組件 B,而組件 B 又依賴于組件 C,組件 C 又依賴于組件 A,就產(chǎn)生了循環(huán)依賴。這種情況應(yīng)通過"依賴倒置原則(Dependency Inversion Principle)"加以避免。
- 軟件包循環(huán):多個(gè)軟件包或插件混亂的相互依賴,而不是形成等級依賴關(guān)系。
- 交叉:依賴于多個(gè)其他類的上帝類,另一方面,眾多不同的類又依賴于這個(gè)特定的類。
為了避免這些架構(gòu)反模式,軟件架構(gòu)師應(yīng)考慮實(shí)施 S.O.L.I.D.原則、GoF 設(shè)計(jì)模式、耦合原則/組件原則。
下面是示例性現(xiàn)金流 Spring Boot 應(yīng)用的 UML,可以在 git 倉庫[2]中查看源代碼。如你所見,該項(xiàng)目由三個(gè)基礎(chǔ)包構(gòu)成:api、core、database,采用分層模式。api負(fù)責(zé)向外部調(diào)用者公開restful API,core包含內(nèi)部所有與業(yè)務(wù)相關(guān)的代碼,而database則專注于數(shù)據(jù)庫層。
現(xiàn)金流應(yīng)用程序的 UML 圖
在研究了現(xiàn)金流應(yīng)用程序的 UML 圖之后,我們來生成系統(tǒng)的依賴結(jié)構(gòu)矩陣(Dependency Structure Matrix)。我通過 Jarchitect[3] 工具生成矩陣,但此外還有很多替代方法:如 Intellij 或 Ndepend[4] 的 DSM[5] 支持。列和行代表 Spring Boot 應(yīng)用程序 src 文件夾中的 Java 類,它們的結(jié)構(gòu)是對稱的。第 8 列是 IncomeService,與第 8 行對應(yīng)的是相同的類/接口。單元格中的數(shù)字表示類之間的靜態(tài)依賴導(dǎo)入。例如第 12 列(ConverterServiceImpl.java)在第4/5/10行中標(biāo)了1,表示該類實(shí)現(xiàn)了 ConverterService、ExpenseConverterService、Service.
現(xiàn)金流應(yīng)用的依賴結(jié)構(gòu)矩陣
為了通過 DSM 找到架構(gòu)債務(wù),人們應(yīng)該尋找:
- 循環(huán)調(diào)用:A 類調(diào)用 B 類,B 類調(diào)用 A 類
- 交叉:數(shù)字大的單元格意味著依賴關(guān)系多
- 數(shù)字應(yīng)圍繞對角線分配:意味著類具有很強(qiáng)的內(nèi)凝性
- 矩陣中的數(shù)字越混亂,意味著依賴結(jié)構(gòu)越不安全
- 評估 S.O.L.I.D 原則,研究持有接口的列數(shù)
參考資料:
- [1]Managing Architecture Debt with Dependency Structure Matrix:https://readmedium.com/51f63b6efb4c
- [2]SOLID Principles Sample: https://github.com/alizeynalli90/solid-principles
- [3]Jarchitect: https://www.jarchitect.com
- [4]Ndepend: https://www.ndepend.com
- [5]DSM: https://www.jetbrains.com/help/idea/dsm-analysis.html