idea如何把包变为模块_让我们将包变成模块系统!
idea如何把包變?yōu)槟K
使用構(gòu)建系統(tǒng)將許多項(xiàng)目分為模塊/子項(xiàng)目( Maven , Gradle , SBT …); 編寫模塊化代碼通常是一件好事。 將代碼分為構(gòu)建模塊主要用于:
- 隔離代碼部分(減少耦合)
- api / impl拆分
- 僅將第三方依賴項(xiàng)添加到代碼的特定部分
- 具有相似功能的代碼分組
- 靜態(tài)檢查一個(gè)模塊中的代碼僅使用其依賴模塊(模塊間依賴)中的代碼
盡管有些人可能說它對于單獨(dú)的編譯也很有用,但我認(rèn)為這并不重要(考慮一個(gè)項(xiàng)目時(shí))。 如今,構(gòu)建工具非常聰明,可以找出需要重新編譯的內(nèi)容。
構(gòu)建模塊問題
我認(rèn)為這種方法存在一些問題。 首先,很難確定何時(shí)某個(gè)功能“足夠大”以將其轉(zhuǎn)換為構(gòu)建模塊。 幾門課就夠了嗎? 還是您需要更多? 嚴(yán)格來說,每個(gè)模塊是否應(yīng)該只有一種功能? 但這會導(dǎo)致模塊爆炸。 等等。 至少在我參與的項(xiàng)目中,這是討論的共同主題,即構(gòu)建模塊的粒度應(yīng)如何粗略。
其次,構(gòu)建模塊非常“繁重”。 我想Maven最糟糕,您需要大量的xml來創(chuàng)建一個(gè)帶有大量樣板文件的模塊(例如,重復(fù)的組ID,版本號,父級定義); SBT和Gradle更好,但仍然是一項(xiàng)巨大的努力。 需要創(chuàng)建一個(gè)單獨(dú)的目錄,整個(gè)目錄結(jié)構(gòu)( src/main/... , src/test/... ),更新構(gòu)建配置等。總的來說,這很麻煩。
然后,當(dāng)我們將漂亮的模塊分開時(shí),經(jīng)常會發(fā)現(xiàn),為了使它們中的兩個(gè)相互協(xié)作,我們需要一個(gè)“通用”部分。 然后,我們要么以一個(gè)腫的foo-common模塊結(jié)束,該模塊包含不相關(guān)類的負(fù)載,要么以多個(gè)小型foo-foomodule-common模塊結(jié)束; 第二種解決方案當(dāng)然沒問題,只是浪費(fèi)時(shí)間進(jìn)行設(shè)置。
最后,構(gòu)建模塊是您還必須命名的其他內(nèi)容。 軟件包名稱和類名稱很可能已經(jīng)反映了代碼的作用,現(xiàn)在還需要在構(gòu)建模塊名稱中重復(fù)(違反DRY)。
總而言之,我認(rèn)為創(chuàng)建構(gòu)建模塊非常困難且耗時(shí)。 程序員是懶惰的(當(dāng)然,這是一件好事),這導(dǎo)致設(shè)計(jì)不像它們可能的那么干凈。 是時(shí)候改變它了:)
(另請參見我之前有關(guān)模塊的博客 。)
配套
Java,Scala和Groovy已經(jīng)有一個(gè)用于對代碼進(jìn)行分組的系統(tǒng):程序包。 但是,當(dāng)前包僅是字符串標(biāo)識符。 除了一些非常有限的可見性選項(xiàng)(在Java中為package-private,在Scala中為package-scoping)之外,軟件包沒有語義。 因此,我們有幾個(gè)級別的分組代碼:
如果我們將2.和3.合并在一起會怎樣? 為什么不應(yīng)該使用軟件包來創(chuàng)建模塊?
包作為模塊?
讓我們來看看將包擴(kuò)展為模塊會怎樣。 顯然,我們需要做的第一件事是將一些元數(shù)據(jù)與每個(gè)模塊相關(guān)聯(lián)。 已經(jīng)有一些機(jī)制(例如,通過package-info.java上的注釋),或者這可能是Scala中軟件包對象的擴(kuò)展-可以混入某些特征,或覆蓋val 。
什么樣的元數(shù)據(jù)? 當(dāng)然,我們不想將整個(gè)構(gòu)建定義移到軟件包中。 但是讓我們分開關(guān)注 –構(gòu)建定義應(yīng)該定義如何構(gòu)建項(xiàng)目,而不是模塊依賴項(xiàng)。 然后,在模塊的元數(shù)據(jù)中定義的第一件事就是對第三方庫的依賴。 這樣的定義可能只是符號,它將被綁定到構(gòu)建定義中的具體版本。
例如,我們將指定包“ foo.bar.dao ”取決于“ jpa ”庫。 然后,構(gòu)建定義將包含從“ jpa ”到Maven工件列表的映射(例如hibernate-core,hibernate-entitymanager等)。 而且,如果這種依賴關(guān)系可以傳遞到子包,則可能最有意義。 因此,定義全局庫將意味著增加對根包的依賴。
附帶說明一下,通過擴(kuò)展Scala的包對象,甚至可以將其設(shè)置為類型安全的。 包對象可以實(shí)現(xiàn)特征,其中要覆蓋的值之一可以是第三方依賴項(xiàng)符號的列表。 符號本身可以包含在根包中定義的Enumeration中; 這可以使諸如“根據(jù)jpa查找所有模塊”之類的事情在IDE中進(jìn)行簡單的用法搜索。
第二步是也使用此機(jī)制定義模塊間依賴關(guān)系。 在包的元數(shù)據(jù)中,可以定義其他包的列表,從中可以看到代碼。 這遵循當(dāng)前構(gòu)建模塊的使用方式:每個(gè)構(gòu)建模塊均包含可訪問的項(xiàng)目模塊的列表。 (另一個(gè)Scala旁注:由于包對象將實(shí)現(xiàn)特征,這意味著定義具有給定類型的對象列表。)
更進(jìn)一步,我們可以指定api和impl類型包。 默認(rèn)情況下,可以從其他軟件包訪問Api型的。 另一方面,如果不將Impl類型的程序包明確指定為依賴項(xiàng),則無法訪問它們。
在實(shí)踐中看起來如何? Scala中的一個(gè)非常粗糙的草圖:
package foo.user// Even without definition, each package has an implicit package object // implementing a PackageModule trait ... package object dao { // ... which is used here. The type of the val below is // List[PackageModule].override val moduleDependsOn = List(foo.security, foo.user.model) override val moduleType = ModuleType.API// FooLibs enum is defined in a top-level package or the build systemoverride val moduleLibraries = List(FooLibs.JPA) }
重構(gòu)
重構(gòu)是日常活動; 但是,重構(gòu)模塊通常是一項(xiàng)艱巨的任務(wù),有時(shí)只能使用一次。 應(yīng)該是這樣嗎? 如果將程序包擴(kuò)展到模塊,則重構(gòu)模塊將與四處移動和重命名程序包相同,另外還需要更新元數(shù)據(jù)。 這將比現(xiàn)在容易得多,我認(rèn)為這將導(dǎo)致更好的總體設(shè)計(jì)。
建立系統(tǒng)
上面的內(nèi)容顯然意味著構(gòu)建系統(tǒng)需要做更多的工作–很難弄清模塊列表,構(gòu)建順序,要創(chuàng)建的工件列表等(順便說一句,如果要為一個(gè)程序包創(chuàng)建一個(gè)單獨(dú)的jar,可以也是元數(shù)據(jù)的一部分)。 此外,還需要進(jìn)行一些驗(yàn)證-循環(huán)依賴關(guān)系,或試圖以錯(cuò)誤的方式限制可見性。
但是后來,人們做了比這更復(fù)雜的軟件
拼圖?
您可能會說,這與項(xiàng)目Jigsaw重疊,后者將在Java 9中(或不是)中出現(xiàn)。 但是,我認(rèn)為Jigsaw的目標(biāo)范圍不同:項(xiàng)目級別的模塊。 因此,一個(gè)拼圖模塊將是您的整個(gè)項(xiàng)目,而您將擁有多個(gè)(數(shù)十個(gè))程序包模塊。
名稱“模塊”在這里是重載的,也許名稱“迷你模塊”會更好,或者適度地“正確地打包”。
底線
我認(rèn)為,當(dāng)前定義構(gòu)建模塊的方法太過困難且受限制。 另一方面,將包裝提升至模塊將非常輕巧。 定義一個(gè)新模塊與創(chuàng)建一個(gè)新程序包相同–簡單得多。 第三方庫只能在需要的地方添加。 少說一件事。 每個(gè)項(xiàng)目只有一棵源樹。
同樣,這種方法可以根據(jù)項(xiàng)目需求進(jìn)行擴(kuò)展和調(diào)整。 無需花費(fèi)太多精力就可以定義細(xì)粒度模塊或粗粒度模塊。 甚至更好的是,為什么不創(chuàng)建兩個(gè)模塊呢?模塊可以嵌套并在另一個(gè)模塊之上構(gòu)建。
現(xiàn)在…唯一的問題是實(shí)現(xiàn)并添加IDE支持;)
參考: 讓我們將包變成模塊系統(tǒng)! 來自我們的JCG合作伙伴 Adam Warski, 網(wǎng)址為Adam Warski博客。
翻譯自: https://www.javacodegeeks.com/2012/11/lets-turn-packages-into-a-module-system.html
idea如何把包變?yōu)槟K
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的idea如何把包变为模块_让我们将包变成模块系统!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发运营单位必须要有地吗(开发运营单位d
- 下一篇: 从微服务到分布式系统-Java开发人员生