熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Java升級篇:ANT十五大最佳實踐詳解

2013-11-23 20:20:55  來源: Java開源技術 

  在Ant出現之前構建和部署Java應用需要使用包括特定平台的腳本Make文件各種版本的IDE甚至手工操作的大雜燴現在幾乎所有的開源Java項目都在使用Ant大多數公司的內部項目也在使用AntAnt在這些項目中的廣泛使用自然導致了讀者對一整套Ant最佳實踐的迫切需求
  
  本文總結了我喜愛的Ant技巧或最佳實踐多數是從我親身經歷的項目錯誤或我聽說的其他人經歷的 恐怖故事中得到靈感的比如有人告訴我有個項目把XDoclet 生成的代碼放入帶有鎖定文件功能的版本控制工具中
  
  當開發者修改源代碼時他必須記住手工檢出(Check out)並鎖定所有將要重新生成的文件然後手工運行代碼生成器只到這時他才能夠讓Ant編譯代碼這一方法還存在如下一些問題
  
  生成的代碼無法存儲在版本控制系統中Ant(本案例中是Xdoclet)應該自動確定下一次構建涉及的源文件而不應由程序員手工確定
  
  Ant的構建文件應該定義好正確的任務依賴關系這樣程序員就不必為了完成構建而不得不按照特定順序調用任務
  
  當我開始一個新項目時我首先編寫Ant構建文件Ant文件明確地定義構建的過程並被團隊中的每個程序員使用本文所列的技巧基於這樣的假定Ant構建文件是一個必須仔細編寫的重要文件它應在版本控制系統中得到維護並被定期進行重構下面是我的十五大Ant最佳實踐
  
   采用一致的編碼規范
  
  Ant用戶有的喜歡有的痛恨其構建文件的XML語法與其跳進這一令人迷惑的爭論中不如讓我們先看一些能保持XML構建文件簡潔的方法
  
  首先也是最重要的花費時間格式化你的XML讓它看上去很清晰不論XML是否美觀Ant都可以工作但是丑陋的XML很難令人讀懂倘若你在任務之間留出空行有規則的縮進每行文字不超過列左右那麼XML令人驚訝地易讀再加上使用能夠高亮XML語法的優秀編輯器或IDE工具你就不會有閱讀的麻煩
  
  同樣精選含意明確容易讀懂的詞匯來命名任務和屬性比如dirreports就比rpts好特定的編碼規范並不重要只要拿出一套規范並堅持使用就行
  
   將buildxml放在項目根目錄中
  
  Ant構建文件buildxml可以放在任何位置但是放在項目頂級目錄中可以保持項目簡潔這是最常用的規范開發者能夠在頂級目錄中找到預期的buildxml把構建文件放在根目錄中也能夠使人容易了解項目目錄樹中不同目錄之間的邏輯關系以下是一個典型的項目目錄層次
  
  [root dir]
  | buildxml
  +src
  +lib (包含第三方 JAR包)
  +build (由 build任務生成)
  +dist (由 build任務生成)
  
  當buildxml在頂級目錄時假設你處於項目某個子目錄中只要輸入ant find compile 命令不需要改變工作目錄就能夠以命令行方式編譯代碼參數find告訴Ant尋找存在於上級目錄中的buildxml並執行
  
   使用單一的構建文件
  
  有人喜歡將一個大項目分解成幾個小的構建文件每個構建文件分擔整個構建過程的一小部分工作這確實是看法不同的問題但是應該認識到將構建文件分割會增加對整體構建過程的理解難度要注意在單一構建文件能夠清楚表現構建層次的情況下不要過工程化(overengineer)
  
  即使你把項目劃分為多個構建文件也應使程序員能夠在項目根目錄下找到核心buildxml盡管該文件只是將實際構建工作委派給下級構建文件也應保證該文件可用
  
   提供良好的幫助說明
  
  應盡量使構建文件自文檔化增加任務描述是最簡單的方法當你輸入ant projecthelp時你就可以看到帶有描述的任務清單比如你可以這樣定義任務
  
  <target name=compile
  description=Compiles code
  output goes to the build dir>
  
  最簡單的規則是把所有你想讓程序員通過命令行就可以調用的任務都加上描述對於一般用來執行中間處理過程的內部任務比如生成代碼或建立輸出目錄等就無法使用描述屬性
  
  這時可以通過在構建文件中加入XML注釋來處理或者專門定義一個help任務當程序員輸入ant help時來顯示詳細的使用說明
  
  <target name=help
  description=Display detailed usage information>
  <echo>Detailed help
  </echo></target>
  
   提供清除任務
  
  每個構建文件都應包含一個清除任務用來刪除所有生成的文件和目錄使系統回到構建文件執行前的初始狀態執行清空任務後還存在的文件都應處在版本控制系統的管理之下比如
  
  <target name=clean
  description=Destroys all
  generated files and dirs>
  <delete dir=${dirbuild}/>
  <delete dir=${dirdist}/>
  </target>
  
  除非是在產生整個系統版本的特殊任務中否則不要自動調用clean任務當程序員僅僅執行編譯任務或其他任務時他們不需要構建文件事先執行既令人討厭又沒有必要的清空任務要相信程序員能夠確定何時需要清空所有文件
  
   使用ANT管理任務從屬關系
  
  假設你的應用由Swing GUI組件Web界面EJB層和公共應用代碼組成在大型系統中你需要清晰地定義每個Java包屬於系統的哪一層否則任何一點修改都要被迫重新編譯成百上千個文件糟糕的任務從屬關系管理會導致過度復雜而脆弱的系統改變GUI面板的設計不應造成Servlet和EJB的重編譯
  
  當系統變得龐大後稍不注意就可能將依賴於客戶端的代碼引入到服務端這是因為典型的IDE項目文件編譯任何文件都使用單一的classpath而Ant能讓你更有效地控制構建活動
  
  設計你的Ant構建文件編譯大型項目的步驟首先編譯公共應用代碼將編譯結果打成JAR包文件然後編譯上一層的項目代碼編譯時依靠第一步產生的JAR文件不斷重復這一過程直到最高層的代碼編譯完成
  
  分步構建強化了任務從屬關系管理如果你工作在底層Java框架上偶然引用到高層的GUI模板組件這時代碼不需要編譯這是由於構建文件在編譯底層框架時在源路徑中沒有包含高層GUI面板組件的代碼
  
   定義並重用文件路徑
  
  如果文件路徑在一個地方一次性集中定義並在整個構建文件中得到重用那麼構建文件更易於理解以下是這樣做的一個例子
  
  <project name=sample
  default=compile basedir=>
  <path id=mon>
  <pathelement
  location=${jdomjarwithpath}/>
  etc </path>
  <path id=classpathclient>
  <pathelement location=
  ${guistuffjarwithpath}/>
  <pathelement location=
  ${anotherjarwithpath}/>
  <! reuse the common classpath >
  <path refid=mon/>
  </path>
  <target name=mon
  depends=prepare>
  <javac destdir=${dirbuild}
  srcdir=${dirsrc}>
  <classpath
  refid=mon/>
  <include
  name=com/oreilly/common/**/>
  </javac>
  </target>
  </project>
  
  當項目不斷增長構建日益復雜時這一技術越發體現出其價值你可能需要為編譯不同層次的應用定義各自的文件路徑比如運行單元測試的運行應用程序的運行Xdoclet的生成JavaDocs的等等不同路徑
  
  這種組件化路徑定義的方法比為每個任務單獨定義路徑要優越得多否則很容易丟失任務從屬關系的軌跡
  
   定義恰當的任務從屬關系
  
  假設dist任務從屬於jar任務那麼哪個任務從屬於compile任務哪個任務從屬於prepare任務呢?Ant構建文件最終定義了任務的從屬關系圖它必須被仔細地定義和維護
  
  應該定期檢查任務的從屬關系以保證構建工作得到正確執行大的構建文件隨著時間推移趨向於增加更多的任務所以到最後可能由於不必要的從屬關系導致構建工作非常困難比如你可能發現在程序員只需編譯一些沒有使用EJB的GUI代碼時又重新生成了EJB代碼
  
  以優化的名義忽略任務的從屬關系是另一種常見的錯誤這種錯誤迫使程序員為了得到恰當的結果必須記住並按照特定的順序調用一串任務更好的做法是提供描述清晰的公共任務這些任務包含正確的任務從屬關系另外提供一套專家任務讓你能夠手工執行個別的構建步驟這些任務不提供完整的構建過程但是讓那些專家用戶在快速而惱人的編碼期間能夠跳過某些步驟
  
   使用屬性
  
  任何需要配置或可能發生變化的信息都應作為Ant屬性定義下來對於在構建文件中多次出現的值也同樣處理屬性既可以在構建文件頭部定義也可以為了更好的靈活性而在單獨的屬性文件中定義以下是在構建文件中定義屬性的樣式
  
  <project name=sample
  default=compile basedir=>
  <property name=dirbuild
  value=build/>
  <property name=dirsrc
  value=src/>
  <property name=jdomhome
  value=/javatools/jdomb/>
  <property name=jdomjar
  value=jdomjar/>
  <
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28340.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.