使用Degraph管理软件包依赖关系
軟件開發(fā)領(lǐng)域的很大一部分是使系統(tǒng)的復(fù)雜性盡可能地低。 但是復(fù)雜性到底是什么? 雖然確切的語義有很大不同,但取決于您詢問的人,大多數(shù)人可能都認(rèn)為這與系統(tǒng)中部件的數(shù)量及其交互有很大關(guān)系。
考慮太空中的大理石,即行星,月亮或恒星。 沒有任何交互,這就像系統(tǒng)可能會(huì)變得無聊。 什么都沒發(fā)生。 如果大理石移動(dòng),它會(huì)以完全相同的方式移動(dòng)。 老實(shí)說,甚至沒有辦法確定它是否在移動(dòng)。 笨蛋。
在系統(tǒng)中添加第二塊大理石,讓它們彼此吸引,就像地球和月亮一樣。 現(xiàn)在,該系統(tǒng)更加有趣。 如果它們不太快,則這兩個(gè)對(duì)象會(huì)彼此繞圈。 有點(diǎn)有趣。
現(xiàn)在添加第三個(gè)對(duì)象。 在一般情況下,事情變得如此有趣,以至于我們甚至無法預(yù)測(cè)會(huì)發(fā)生什么。 整個(gè)系統(tǒng)不僅變得復(fù)雜,而且變得混亂。 您現(xiàn)在有一個(gè)三體問題 。在一般情況下,此問題無法解決,即我們無法預(yù)測(cè)系統(tǒng)會(huì)發(fā)生什么。 但是有一些特殊情況。 尤其是其中兩個(gè)對(duì)象彼此非常接近的情況(例如地球和月亮),而第三個(gè)對(duì)象相距太遠(yuǎn),以至于兩個(gè)第一個(gè)對(duì)象的行為就像一個(gè)對(duì)象。 在這種情況下,您可以用兩個(gè)粒子系統(tǒng)來近似該系統(tǒng)。
但是,這與Java有什么關(guān)系? 這聽起來更像物理學(xué)。
我認(rèn)為軟件開發(fā)在某些方面是相似的。 完整的應(yīng)用程序是從整體上變得復(fù)雜的方式。 為了克服這種復(fù)雜性,我們將系統(tǒng)分為可以自己理解的部分(類),并隱藏了它們的內(nèi)部復(fù)雜性,這樣,當(dāng)我們查看較大的圖片時(shí),不必?fù)?dān)心代碼中的每個(gè)代碼行類,但僅將類作為一個(gè)實(shí)體。 實(shí)際上,這與物理學(xué)家對(duì)系統(tǒng)所做的非常相似。
但是,讓我們看一下事物的規(guī)模。 軟件的基本構(gòu)建塊是代碼行。 為了控制復(fù)雜性,我們將在方法中一起工作的代碼行捆綁在一起。 單個(gè)方法中有多少行代碼會(huì)有所不同,但大約為10行代碼。
接下來,將方法收集到類中。 一個(gè)類中有多少種方法? 通常按10種方法排序!
然后? 我們將100-10000個(gè)班級(jí)捆綁在一個(gè)罐中! 我希望我不是唯一認(rèn)為某事不對(duì)勁的人。
我不確定從Jigsaw項(xiàng)目中會(huì)得到什么,但是目前Java僅提供軟件包來捆綁類。 包并不是一個(gè)強(qiáng)大的抽象,但是它是我們唯一的抽象,因此我們最好使用它。
大多數(shù)團(tuán)隊(duì)確實(shí)使用軟件包,但不是以非常結(jié)構(gòu)化但臨時(shí)的方式使用軟件包。 結(jié)果類似于試圖將月亮和太陽視為系統(tǒng)的一部分,而將地球視為另一部分。 結(jié)果可能有效,但可能與托勒密的行星模型一樣直觀。 取而代之的是,根據(jù)標(biāo)準(zhǔn)確定如何區(qū)分包裝。 我個(gè)人稱它們?yōu)榍衅?#xff0c;是受Oliver Gierke的一篇文章的啟發(fā)。 按重要性順序排列的可能切片為:
- 該類最終應(yīng)位于的可部署jar文件
- 類所屬的用例/功能/業(yè)務(wù)模型的一部分
- 類所屬的技術(shù)層
結(jié)果生成的軟件包將如下所示:<domain>。<deployable>。<domain part>。<layer>
決定去哪兒上課應(yīng)該很容易。 并且即使您不使用技術(shù)層分隔,它也應(yīng)將包裝保持在合理的尺寸。
但是,您從中得到什么呢? 找到類比較容易,但是僅此而已。 您還需要一個(gè)規(guī)則來使它真正值得: 不得有循環(huán)依賴項(xiàng)!
這意味著,如果包A中的類引用了包B中的類,則B中的任何類都不能引用A。如果引用是通過多個(gè)其他包間接引用的,則這也適用。 但這還不夠。 切片也應(yīng)該是無周期的,因此,如果域部分X引用了其他域部分Y,則反向依賴性一定不存在!
實(shí)際上,這將對(duì)您的程序包和依賴項(xiàng)結(jié)構(gòu)設(shè)置一些相當(dāng)嚴(yán)格的規(guī)則。 這樣做的好處是,它變得非常靈活。
沒有這樣的結(jié)構(gòu),將您的項(xiàng)目分成多個(gè)部分可能會(huì)很困難。 是否曾經(jīng)嘗試過在另一個(gè)應(yīng)用程序中重用應(yīng)用程序的一部分,只是為了意識(shí)到您必須包含大部分應(yīng)用程序才能進(jìn)行編譯? 是否曾經(jīng)嘗試將應(yīng)用程序的不同部分部署到不同的服務(wù)器,只是為了意識(shí)到自己做不到? 在使用上述方法之前,這肯定發(fā)生在我身上。 但是,通過這種更嚴(yán)格的結(jié)構(gòu),您可能想重用的部分將幾乎完全依賴于依賴鏈的末端,因此您可以將它們打包并捆綁在自己的jar中,或者只是將代碼復(fù)制到不同的容器中項(xiàng)目并在很短的時(shí)間內(nèi)進(jìn)行編譯。
同樣,在嘗試保持軟件包和分片周期自由的同時(shí),您將不得不認(rèn)真思考,每個(gè)涉及的軟件包實(shí)際上都是關(guān)于什么的。 在許多情況下,這些可以極大地改善我的代碼庫(kù)。
因此,剩下一個(gè)問題:依賴關(guān)系很難看到。 沒有工具,很難保持代碼庫(kù)的自由。 當(dāng)然,有很多工具可以檢查周期,但是清理這些周期很困難,而且大多數(shù)工具提供這些周期的方式也無濟(jì)于事。 我認(rèn)為一個(gè)需求是兩件事:
驚喜! 我可以推薦一個(gè)很棒的工具: Degraph ! (我是作者,所以我可能會(huì)有偏見)
您可以像這樣在JUnit中編寫測(cè)試:
assertThat( classpath().including("de.schauderhaft.**") .printTo("degraphTestResult.graphml") .withSlicing("module", "de.schauderhaft.(*).*.**") .withSlicing("layer", "de.schauderhaft.*.(*).**"), is(violationFree()) );該測(cè)試將分析類路徑中以de.schauderhaft開頭的所有內(nèi)容。 它將以兩種方式對(duì)類進(jìn)行切片:通過獲取包名稱的第三部分和通過獲取包名稱的第四部分。 因此,類名de.schauderhaft.customer.persistence.HibernateCustomerRepository最終出現(xiàn)在模塊客戶和層持久性中。 并且它將確保模塊,層和包是無周期的。
并且,如果找到依賴項(xiàng)圓,它將創(chuàng)建一個(gè)graphml文件,您可以使用免費(fèi)的圖形編輯器yed打開該文件 。 通過一點(diǎn)布局,您將得到如下所示的結(jié)果,其中導(dǎo)致循環(huán)依賴關(guān)系的依賴關(guān)系被標(biāo)記為紅色。
同樣,有關(guān)如何實(shí)現(xiàn)良好的可用布局的更多詳細(xì)信息,我必須參考Degraph的文檔 。
另請(qǐng)注意,圖表主要以綠色為主,并帶有少許紅色,非常適合本季節(jié)!
翻譯自: https://www.javacodegeeks.com/2014/12/managing-package-dependencies-with-degraph.html
總結(jié)
以上是生活随笔為你收集整理的使用Degraph管理软件包依赖关系的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓我的文明无限钻石(安卓我的文明)
- 下一篇: 具有CompletableFuture的