Maven实战(二)——POM重构之增还是删
重構(gòu)是廣大開發(fā)者再熟悉不過(guò)的技術(shù),在Martin Fowler的《重構(gòu)——改善既有代碼的設(shè)計(jì)》一書中,其定義為“重構(gòu)(名詞):對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件之可察行為前提下,提高其可理解性,降低其修改成本.”以及“重構(gòu)(動(dòng)詞):使用一系列重構(gòu)準(zhǔn)則(手法),在不改變軟件之可察行為前提下,調(diào)整其結(jié)構(gòu).”。重構(gòu)能夠改善軟件設(shè)計(jì),使代碼更易讀,更容易找出bug,并幫助你更快速地編碼。較之于一般的代碼來(lái)說(shuō),Maven的POM簡(jiǎn)單很多,不過(guò)隨著項(xiàng)目的成長(zhǎng),模塊的增多,POM的內(nèi)容也會(huì)變多,這個(gè)時(shí)候,我們可以對(duì)POM進(jìn)行重構(gòu),在保持構(gòu)建成功的前提下,簡(jiǎn)化POM內(nèi)容,使其更簡(jiǎn)潔易懂。
前提
大家都知道,如果沒有單元測(cè)試為前提,對(duì)代碼進(jìn)行重構(gòu)是非常危險(xiǎn)的。同樣,在重構(gòu)POM之前,項(xiàng)目應(yīng)該有足夠的自動(dòng)化測(cè)試保證POM重構(gòu)不會(huì)破壞構(gòu)建。例如,重構(gòu)POM的時(shí)候可能會(huì)刪除或添加依賴,造成依賴版本變化,依賴范圍變化,插件版本變化等等,這些變化可能會(huì)導(dǎo)致項(xiàng)目編譯失敗,或者測(cè)試失敗。在自動(dòng)化測(cè)試及構(gòu)建的基礎(chǔ)上,最好能夠有持續(xù)集成環(huán)境,以保證POM的修改可能造成的問(wèn)題能夠及時(shí)的被發(fā)現(xiàn)和修復(fù)。筆者目前工作的項(xiàng)目有一個(gè)對(duì)應(yīng)的持續(xù)集成任務(wù),該任務(wù)基于Hudson,每10分鐘檢查一次SCM,如果發(fā)現(xiàn)變更則構(gòu)建項(xiàng)目,并反饋結(jié)果。這樣,我就不用擔(dān)心自己修改POM會(huì)引入潛在的問(wèn)題。
增還是刪
有時(shí)候這個(gè)答案是很顯然的,當(dāng)你的POM中存在一些依賴或者插件配置,但實(shí)際代碼沒有用到這些配置的時(shí)候,應(yīng)該盡早刪掉它們以免給人帶來(lái)困惑。
還有一種常見的情況,我們可以刪掉一些POM的元素,例如POM中配置了繼承,當(dāng)前模塊與父模塊使用同樣的groupId和version時(shí),就可以將<groupId>和<version>元素刪除,因?yàn)樗鼈兛梢詮母改K繼承而來(lái),重復(fù)配置沒有什么意義。
<project><modelVersion>4.0.0</modelVersion><parent><groupId>com.juvenxu.sample</groupId><artifactId>sample-parent</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>sample-foo</artifactId><packaging>jar</packaging> ... </project>上述配置就sample-foo就沒有g(shù)roupId和version,需要注意的是,artifactId是不能被刪除的,因?yàn)樵撛夭荒芤膊粦?yīng)該被繼承,父子模塊應(yīng)當(dāng)使用不同的artifactId值。
除了刪之外,有些時(shí)候我們還需要在POM中增加一些XML元素,目的是為了讓POM更清晰易讀,且保證Maven構(gòu)建的穩(wěn)定性。考慮如下的插件配置:
<plugin><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.5</source><target>1.5</target></configuration> </plugin>雖然沒有g(shù)roupId及version,但這段配置是完全合法的。當(dāng)插件沒有g(shù)roupId配置的時(shí)候,Maven會(huì)認(rèn)為它是官方插件而自動(dòng)使用org.apache.maven.plugins作為groupId,當(dāng)插件沒有version配置的時(shí)候,Maven則會(huì)使用最新的版本(Maven 2會(huì)使用最新的版本,包括SNAPSHOT,而Maven 3則只使用最新的非SNAPSHOT版本)。這段配置有兩個(gè)問(wèn)題,首先,如果讓一個(gè)不熟悉Maven的開發(fā)者來(lái)看這段配置,他會(huì)感到費(fèi)解,groupId和version究竟是什么呢?這與不清晰的代碼是一個(gè)意思,有時(shí)候一些程序員為了讓代碼更短,會(huì)采用一些奇怪的語(yǔ)法和變量名,雖然代碼量是少了,但溝通成本增加了,得不償失。其次,讓Maven猜測(cè)版本會(huì)有潛在的風(fēng)險(xiǎn),因?yàn)椴寮淖钚掳姹究赡軙?huì)變化,而這種變化對(duì)于Maven使用者來(lái)說(shuō)通常是隱藏的,特別是在Maven 2中,甚至可能引入SNAPSHOT版本的插件,這是非常危險(xiǎn)的。基于這兩個(gè)原因,使用插件的時(shí)候,我們應(yīng)當(dāng)配置清楚groupId和version,如:
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.5</source><target>1.5</target></configuration> </plugin>基于類似的原因,在配置項(xiàng)目依賴的時(shí)候,我們也應(yīng)當(dāng)一直顯式地寫明依賴版本,以避免Maven在不同的時(shí)刻引入不同版本的依賴而導(dǎo)致項(xiàng)目構(gòu)建的不穩(wěn)定。
除了上面提到的增刪點(diǎn)之外,Maven官方還提供了一個(gè)非常有用的Maven Dependency Plugin來(lái)幫助我們分析項(xiàng)目中哪些依賴配置應(yīng)該刪除,那些依賴配置應(yīng)該增加。Maven Dependency Plugin的analyze目標(biāo)能夠幫助分析項(xiàng)目依賴,例如運(yùn)行命令?mvn dependency:analyze?,可以看到如下輸出:
[INFO]?---?maven-dependency-plugin:2.1:analyze?(default-cli)?@?sample-bar?--- [WARNING]?Used?undeclared?dependencies?found: [WARNING]????org.springframework:spring-context:jar:2.5.6:compile [WARNING]?Unused?declared?dependencies?found: [WARNING]????org.springframework:spring-core:jar:2.5.6:compile [WARNING]????org.springframework:spring-beans:jar:2.5.6:compile [INFO]?------------------------------------------------------------------------這里的 Used undeclared dependencies 是指那些在項(xiàng)目中直接使用到的,但沒有在POM中配置的依賴。例如該例中可能項(xiàng)目中的一些類有關(guān)于spring-context的Java import聲明,但spring-context這個(gè)依賴實(shí)際是通過(guò)傳遞性依賴進(jìn)入classpath的,這就意味者潛在的風(fēng)險(xiǎn)。一般來(lái)說(shuō)我們對(duì)直接依賴的版本變化會(huì)比較清楚,因?yàn)槟鞘俏覀冏约褐苯优渲玫?#xff0c;但對(duì)于傳遞性依賴的版本變化,就會(huì)比較模糊,當(dāng)這種變化造成構(gòu)建失敗的時(shí)候,就很難找到原因。因此我們應(yīng)當(dāng)增加這些 Used undeclared dependencies 。
依賴分析還提供了 Unused declared dependencies 供我們參考,這表示那些我們配置了,但并未直接使用的依賴。需要注意的時(shí),對(duì)于這些依賴,我們不該直接簡(jiǎn)單地刪除。由于dependency:analyze只分析編譯主代碼和測(cè)試代碼使用的依賴,一些執(zhí)行測(cè)試和運(yùn)行時(shí)的依賴它發(fā)現(xiàn)不了,因此還需要人工分析。通常情況,Unused declared dependencies 還是能幫助我們發(fā)現(xiàn)一些無(wú)用的依賴配置。
最后,還一些重要的POM內(nèi)容通常被大多數(shù)項(xiàng)目所忽略,這些內(nèi)容不會(huì)影響項(xiàng)目的構(gòu)建,但能方便信息的溝通,它們包括項(xiàng)目URL,開發(fā)者信息,SCM信息,持續(xù)集成服務(wù)器信息等等,這些信息對(duì)于開源項(xiàng)目來(lái)說(shuō)尤其重要。對(duì)于那些想了解項(xiàng)目的人來(lái)說(shuō),這些信息能他們幫助找到想要的信息,基于這些信息生成的Maven站點(diǎn)也更有價(jià)值。相關(guān)的POM配置很簡(jiǎn)單,如:
<project><description>...</description><url>...</url><licenses>...</licenses><organization>...</organization><developers>...</developers><issueManagement>...</issueManagement><ciManagement>...</ciManagement><mailingLists>...</mailingLists><scm>...</scm> </project>小結(jié)
無(wú)論是對(duì)POM內(nèi)容進(jìn)行增還是刪,其目的都是一樣的,就是為了讓POM更清晰易懂且讓構(gòu)建更穩(wěn)定。從這點(diǎn)來(lái)說(shuō),POM重構(gòu)與一般的代碼重構(gòu)是類似的。需要謹(jǐn)記的是,重構(gòu)的前提是完善的自動(dòng)化測(cè)試和持續(xù)集成。本文介紹的單個(gè)POM規(guī)模的重構(gòu),下篇文章筆者會(huì)介紹多模塊項(xiàng)目的POM重構(gòu)等內(nèi)容。
關(guān)于作者
許曉斌(Juven Xu),國(guó)內(nèi)社區(qū)公認(rèn)的Maven技術(shù)專家、Maven中文用戶組創(chuàng)始人、Maven技術(shù)的先驅(qū)和積極推動(dòng)者。對(duì)Maven有深刻的認(rèn)識(shí),實(shí)戰(zhàn)經(jīng)驗(yàn)豐富,不僅撰寫了大量關(guān)于Maven的技術(shù)文章,而且還翻譯了開源書籍《Maven權(quán)威指南》,對(duì)Maven技術(shù)在國(guó)內(nèi)的普及和發(fā)展做出了很大的貢獻(xiàn)。就職于Maven之父的公司,負(fù)責(zé)維護(hù)Maven中央倉(cāng)庫(kù),是Maven倉(cāng)庫(kù)管理器Nexus(著名開源軟件)的核心開發(fā)者之一,曾多次受邀到淘寶等大型企業(yè)開展Maven方面的培訓(xùn)。此外,他還是開源技術(shù)的積極倡導(dǎo)者和推動(dòng)者,擅長(zhǎng)Java開發(fā)和敏捷開發(fā)實(shí)踐。他的個(gè)人網(wǎng)站是:http://www.juvenxu.com。
轉(zhuǎn)自:http://www.infoq.com/cn/news/2010/12/xxb-maven-2-pom?utm_source=news_about_maven-practice&utm_medium=link&utm_campaign=maven-practice
轉(zhuǎn)載于:https://blog.51cto.com/guomingzhang/1885847
總結(jié)
以上是生活随笔為你收集整理的Maven实战(二)——POM重构之增还是删的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 详解XStream别名
- 下一篇: Mybatis中的collection、