讓我們將包變成模塊系統!

使用構建系統將許多項目分為模塊/子項目( Maven , Gradle , SBT …); 編寫模塊化代碼通常是一件好事。 將代碼分為構建模塊主要用于:

  • 隔離代碼部分(減少耦合)
  • api / impl拆分
  • 僅將第三方依賴項添加到代碼的特定部分
  • 具有相似功能的代碼分組
  • 靜態檢查一個模塊中的代碼僅使用其依賴模塊(模塊間依賴)中的代碼

盡管有些人可能說它對于單獨的編譯也很有用,但我認為這并不重要(考慮一個項目時)。 如今,構建工具非常聰明,可以找出需要重新編譯的內容。

構建模塊問題

我認為這種方法存在一些問題。 首先,很難確定何時某個功能“足夠大”以將其轉換為構建模塊。 幾門課就夠了嗎? 還是您需要更多? 嚴格來說,每個模塊是否應該只有一種功能? 但這會導致模塊爆炸。 等等。 至少在我參與的項目中,這是討論的共同主題,即構建模塊的粒度應如何粗略。

其次,構建模塊非常“繁重”。 我想Maven最糟糕,您需要一個很大的xml來創建一個模塊,其中包含許多樣板(例如重復的組ID,版本號,父級定義); SBT和Gradle更好,但是,這仍然是一項巨大的努力。 需要創建一個單獨的目錄,整個目錄結構( src/main/...src/test/... ),更新構建配置等。總的來說,這很麻煩。

然后,當我們經常將漂亮的模塊分開時,事實證明,要使其中兩個模塊相互協作,我們需要一個“通用”部分。 然后,我們要么以一個blo腫的foo-common模塊結束,其中包含不相關的類,要么是多個小型foo-foomodule-common模塊; 第二種解決方案當然可以,只是浪費時間進行設置。

最后,構建模塊是您還必須命名的其他內容。 包名稱和類名稱很可能已經反映了代碼的作用,現在還需要在構建模塊名稱中重復(違反DRY)。

總而言之,我認為創建構建模塊非常困難且耗時。 程序員是懶惰的(這當然是一件好事),這導致設計不像它們可能的那么干凈。 是時候改變它了:)。

(另請參見我先前的模塊博客 。)

配套

Java,Scala和Groovy已經有一個用于對代碼進行分組的系統:程序包。 但是,當前包僅是字符串標識符。 除了一些非常有限的可見性選項(在Java中為package-private,在Scala中為package-scoping)之外,軟件包沒有語義。 因此,我們有幾個級別的分組代碼:

  1. 項目
  2. 構建模塊

如果我們將2.和3.合并在一起會怎樣? 為什么不應該使用軟件包來創建模塊?

包作為模塊?

讓我們來看看將包擴展為模塊需要做什么。 顯然,我們需要做的第一件事是將一些元數據與每個模塊相關聯。 已經有一些機制(例如,通過package-info.java上的注釋),或者這可能是Scala中軟件包對象的擴展-可以混入某些特征,或覆蓋val

什么樣的元數據? 當然,我們不想將整個構建定義移到軟件包中。 但是讓我們分開關注 –構建定義應該定義如何構建項目,而不是模塊依賴項。 然后,在模塊的元數據中定義的第一件事就是對第三方庫的依賴。 這樣的定義可能只是符號,它將被綁定到構建定義中的具體版本。

例如,我們將指定包“ foo.bar.dao ”取決于“ jpa ”庫。 然后,構建定義將包含從“ jpa ”到Maven工件列表的映射(例如hibernate-core,hibernate-entitymanager等)。 而且,如果這種依賴關系可以傳遞到子包,則可能最有意義。 因此,定義全局庫將意味著增加對根包的依賴。

附帶說明一下,通過擴展Scala的包對象,甚至可以將其設置為類型安全的。 包對象可以實現特征,其中要覆蓋的值之一可以是第三方依賴項符號的列表。 符號本身可以包含在根包中定義的Enumeration中; 這可以使諸如“根據jpa查找所有模塊”之類的事情在IDE中進行簡單的用法搜索。

第二步也是使用此機制定義模塊間的依賴關系。 在包的元數據中,可以定義其他包的列表,從中可以看到代碼。 這遵循當前使用的構建模塊的方式:每個模塊都包含可訪問的項目模塊的列表。 (另一個Scala旁注:由于包對象將實現特征,因此這意味著定義具有給定類型的對象列表。)

進一步講,我們可以指定apiimpl類型包。 默認情況下,可以從其他軟件包訪問Api型的。 另一方面,如果未明確將Impl類型的程序包指定為依賴項,則無法訪問它們。

在實踐中看起來如何? Scala中的一個非常粗糙的草圖:

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) 
}


重構

重構是日常活動; 但是,重構模塊通常是一項艱巨的任務,偶爾需要處理一次。 應該是這樣嗎? 如果將程序包擴展到模塊,則重構模塊將與移動和重命名程序包相同,另外還需要更新元數據。 這將比現在容易得多,我認為這將導致更好的總體設計。

建立系統

上面的內容顯然意味著構建系統需要做更多的工作–很難確定模塊列表,構建順序,要創建的工件列表等(順便說一句,如果要為一個程序包創建一個單獨的jar,可以也是元數據的一部分)。 此外,還需要進行一些驗證-對于循環依賴關系,或試圖以錯誤的方式限制可見性。

但是后來,人們做了比這更復雜的軟件

拼圖?

您可能會說,這與項目Jigsaw重疊,后者將在Java 9中(或不是)中出現。 但是,我認為Jigsaw的目標范圍不同:項目級別的模塊。 因此,一個拼圖模塊將是您的整個項目,而您將擁有多個(數十個)軟件包模塊。

名稱“模塊”在這里是重載的,也許名稱“迷你模塊”會更好,或者非常謙虛地“正確地打包”。

底線

我認為,當前定義構建模塊的方法太過困難且受限制。 另一方面,將包裝提升到模塊將非常輕便。 定義一個新模塊與創建一個新程序包相同–簡單得多。 第三方庫只能在需要的地方添加。 少一件事。 每個項目只有一個源樹。

同樣,這種方法將可擴展并可根據項目需求進行調整。 無需花費太多精力就可以定義細粒度模塊或粗粒度模塊。 甚至更好的是,為什么不創建兩個模塊呢?模塊可以嵌套并在另一個模塊之上構建。

現在…唯一的問題是實現并添加IDE支持;)

參考: 讓我們將包變成模塊系統! 來自我們的JCG合作伙伴 Adam Warski, 來自Adam Warski博客的Blog。

翻譯自: https://www.javacodegeeks.com/2012/11/lets-turn-packages-into-a-module-system.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371146.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371146.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371146.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

R語言日期的表示和運算(詳細總結)

1、取出當前日期 Sys.Date() [1] "2014-10-29" date() #注意:這種方法返回的是字符串類型 [1] "Wed Oct 29 20:36:07 2014" 2、在R中日期實際是double類型,是從1970年1月1日以來的天數 typeof(Sys.Date()) [1] "double" …

html高度塌陷問題解決

高度塌陷的問題: 當開啟元素的BFC以后,元素將會有如下的特性 1 父元素的垂直外邊距不會和子元素重疊 開啟BFC的元素不會被浮動元素所覆蓋 開啟BFC的元素可以包含浮動的子元素 如何開啟元素的BFC 設置元素浮動 設置元素絕對定位 …

java空格鍵_Java KeyPressed-如果其他鍵也太舊,則無法檢測是否按下了空格鍵

如標題所示,在我的Java游戲中,無法檢測是否同時按下空格鍵和其他鍵。例如,空格鍵是射擊鍵,而箭頭鍵則使玩家移動。如果我按下向上箭頭鍵,向左箭頭鍵和空格鍵,那么它應該向左上方發射子彈。但是,…

How to fix the bug “Expected required, optional, or repeated.”?

參考:https://github.com/tensorflow/models/issues/1834 You need to download protoc version 3.3 (already compiled). Used protoc inside bin directory to run this command like this:tensorflow$ mkdir protoc_3.3tensorflow$ cd protoc_3.3tensorflow/prot…

立面設計模式–設計觀點

在上一篇文章中,我們描述了適配器設計模式 。 在今天的文章中,我們將展示另一種類似的“四結構幫派”模式 。 顧名思義,結構模式用于從許多不同的對象形成更大的對象結構。 外觀模式就是這樣一種模式,它為系統內的一組接口提供了簡…

Java第三次作業 1502 馬 帥

《Java技術》第三次作業 (一)學習總結 1.書中對面向對象封裝性的定義為:指把對象的屬性和行為看成一個密不可分的整體,把不需要讓外界知道的信息隱蔽起來。簡單來說,就是定義的一些對象,只有在本類中才可以…

sass運算

sass具有運算的特性,可以對數值型的Value(如:數字、顏色、變量等)進行加減乘除四則運算。 請注意運算符前后請留一個空格,不然會出錯。 scss.style css.style 本文轉載于:猿2048https://www.mk2048.com/blog/blog.php?idiij12j&titles…

163 coremail_Icoremail企業郵箱

高速穩定iCoremail企業郵箱于國內外多個網絡運營商的主干網數據中心放置郵件服務器,同時采用我司自主研發的Coremail電子郵件系統,從多方面保障了用戶的流暢體驗。安全可靠iCoremail企業郵箱使用歐洲最大的反病毒安全提供商的Sophos反病毒系列產品&#…

jquery-基礎事件[下]

<script>$(function () {mouseover mouseout mouseenter mouseleave的區別$(div).mouseover(function () {$(this).css(background, red);}).mouseout(function () {$(this).css(background, green);});$(div).mouseenter(function () {$(this).css(background, red);}).…

JavaOne 2012:NetBeans.Next –未來路線圖

我從Continental Ballroom 4和一個NetBeans主題&#xff08; 項目Easel &#xff09;到Continental Ballroom 5&#xff0c;走了必要的幾個步驟&#xff0c;以查看另一個面向NetBeans的演示文稿&#xff1a;“ NetBeans.Next –未來路線圖”。 Ashwin Rao發起了“羽毛之鳥”&am…

LeetCode day30

LeetCode day30 害&#xff0c;昨天和今天在搞數據結構的報告&#xff0c;后面應該也會把哈夫曼的大作業寫上來。 今天認識認識貪心算法。(&#xff61;&#xff65;?&#xff65;)&#xff89; 2697. 字典序最小回文串 給你一個由 小寫英文字母 組成的字符串 s &#xff0c;…

html注冊表

這是第一次使用html寫一個簡單的注冊表&#xff08;有不對的地方希望大家可以幫我指出來謝謝?&#xff09; <!DOCTYPE html><html><head> <title>木木音樂網第一次注冊表</title></head><body><h2>使用手機號碼注冊</…

C#復習正則表達式

由于前段時間為了寫工具學的太J8粗糙 加上最近一段時間太浮躁 所以靜下心來復習 一遍以前學的很弱的一些地方1 委托 public delegate double weituo(double a, double b);public static double test1(double a,double b){return a * b;}public static double test2(double a,…

使用JPA偵聽器的數據庫加密

最近&#xff0c;我不得不將數據庫加密添加到幾個字段中&#xff0c;并且發現了很多不好的建議。 建筑問題 最大的問題是建筑。 如果持久性管理器悄悄地處理您的加密&#xff0c;那么根據定義&#xff0c;您的體系結構將在持久性和安全性設計之間要求緊密而不必要的綁定。 您…

Java是先難后易嗎_在解決問題的時候,是先難后易還是先易后難?

有家長問&#xff0c;孩子一旦聽到不同聲音&#xff0c;就沮喪&#xff0c;一旦有難的事情&#xff0c;就逃避&#xff0c;怎么辦&#xff1f;回答這個問題之前&#xff0c;我們問一個問題“你給孩子玩穿紐扣游戲&#xff0c;是一開始給孩子玩容易穿的紐扣好呢&#xff1f;還是…

在vue中安裝使用vux

最近因為的工作的原因在弄vue&#xff0c;從后端弄到前端之前一直用js&#xff0c;現在第一次接觸vue感覺還挺有意思的&#xff0c;就是自己太菜了&#xff0c;這個腦子呀。。。。不太夠用。。。。。頁面設計用了一個叫vux的東西&#xff0c;vux可以提供一些組件&#xff0c;用…

form表單 獲取與賦值

form表單中使用頻繁的組件: 文本框、單選框、多選框、下拉框、文本域form通過getValues()獲取表單中所有name的值 通過setValues({key:values})給對應的name值進行賦值&#xff0c;其中key對應的name值 在給單選框和多選框賦值時&#xff0c;有幾個疑惑的地方&#xff1a;  …

Zabbix全方位告警接入-電話/微信/短信都支持

http://www.cnblogs.com/baidu-gaojing/p/5128035.html 百度告警平臺地址&#xff1a; http://gaojing.baidu.com 聯系我們&#xff1a; 郵箱&#xff1a;gaojingbaidu.com 電話&#xff1a;13924600771 QQ群&#xff1a;183806029 對于使用zabbix的用戶&#xff0c;要接入百度…

Spring MVC定制用戶登錄注銷實現示例

這篇文章描述了如何實現對Spring MVC Web應用程序的自定義用戶訪問&#xff08;登錄注銷&#xff09;。 作為前提&#xff0c;建議讀者閱讀這篇文章 &#xff0c;其中介紹了一些Spring Security概念。 該代碼示例可從Spring-MVC-Login-Logout目錄中的Github獲得。 它從帶有注釋…

HTML5與CSS3權威指南筆記案例1

第1章 <!DOCTYPE html> <meta charset "UTF-8"> <title> Search </title> <form> <p><label>Search&#xff1a;<input name"search" autofocus></label> </p> </form> <!DOCTYPE&…