<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 56, comments - 77, trackbacks - 0, articles - 1
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    Large Scale 的應(yīng)用通常意味著:

    1. 目錄較多, 層次較深

    2. 依賴較多, 構(gòu)建腳本依賴的第三方Ant Task, 項(xiàng)目依賴的第三方庫(kù)等

    3. 測(cè)試較多, 構(gòu)建時(shí)間反饋周期較長(zhǎng)

    4. 需要在不同操作系統(tǒng)上運(yùn)行

    5. 需要在不同團(tuán)隊(duì)成員的機(jī)器上運(yùn)行

    6. 由于以上原因, 導(dǎo)致Ant腳本較長(zhǎng)

     

    1. 目錄較多, 層次較深

    通常有兩種風(fēng)格的解決方案

    1. 一是使用Ant-Contrib中的<foreach>來(lái)遍歷子目錄并依次調(diào)用其中的構(gòu)建腳本, 一般是缺省的target

    2. 另外一種是用Ant自身的<subant>命令來(lái)搜索構(gòu)建腳本并調(diào)用特定的target

    第一種方案可看作深度優(yōu)先, 不同的子目錄通常是系統(tǒng)的不同組件, 這種方式是把單個(gè)組件全部構(gòu)建完再構(gòu)建另外的組件

    第二種方案可看作廣度優(yōu)先, 類似于模板方法, 要求每個(gè)子系統(tǒng)的構(gòu)建腳本都要定義特定的約定的target, Root構(gòu)建腳本會(huì)先調(diào)用所有構(gòu)建腳本的某個(gè)target, 再調(diào)用另外的target

    當(dāng)然也可以用<foreach>來(lái)實(shí)現(xiàn)第二種風(fēng)格

    2. 依賴較多, 構(gòu)建腳本依賴的第三方Ant Task, 項(xiàng)目依賴的第三方庫(kù)等

    1. 明確區(qū)分構(gòu)建腳本的依賴和你的項(xiàng)目的依賴. 那些第三方的Ant Task通常你只會(huì)在構(gòu)建過(guò)程中用到它們, 而不會(huì)在產(chǎn)品中用到, 如 Checkstyle, Emma 等, 把它們放在單獨(dú)的目錄中, 打包時(shí)不要理會(huì)它們. 關(guān)于區(qū)分不同依賴的經(jīng)驗(yàn), 參考<<CruiseControl Enterprise 最佳實(shí)踐 (2) : Keep your dependencies to yourself>>

    2. 使用 ivy 來(lái)管理你項(xiàng)目的依賴

    3. 清理不必要的依賴或干擾:

    1. 總是提供 <clean> target, 并借助工具保證在需要的時(shí)刻總是能夠得到執(zhí)行, 參見后面的章節(jié)

    2. 定義單獨(dú)的目錄來(lái)存放項(xiàng)目所有的輸出, 通常是頂級(jí)目錄下的名字叫做 target或者build或者dist之類的目錄, 其內(nèi)部的層次結(jié)構(gòu)應(yīng)該與源文件的目錄結(jié)構(gòu)一致

    3. 構(gòu)建過(guò)程中拷貝需要的資源到上面定義的輸出目錄中, 而不是直接對(duì)資源操作

    3. 測(cè)試較多, 構(gòu)建反饋周期較長(zhǎng)

    一般你不會(huì)希望直到構(gòu)建過(guò)程的末尾某個(gè)任務(wù)才失敗, 這樣你修正后不得不從頭再跑一遍來(lái)校驗(yàn), 有幾種方式來(lái)來(lái)縮短反饋時(shí)間

    1. 一種是先運(yùn)行最可能失敗的任務(wù), 利用前面提到的<subant><foreach>

    2. 一種是為每個(gè)任務(wù)都定義單獨(dú)的target, 或用"property"來(lái)選擇或忽略特定的target. 參見 target 的 if/unless 屬性, 及 Condition 元素. 如用property來(lái)控制運(yùn)行所有測(cè)試還是某個(gè)測(cè)試:

        <junit ...>

          <!-- ... -->

          <test name="${testcase}" if="testcase"/>

          <batchtest todir="${test.data.dir}" unless="testcase">

              <fileset dir="${test.classes.dir}" includes="**/*Test.class" />

          </batchtest>

        </junit>

    另外你希望一次構(gòu)建能夠發(fā)現(xiàn)盡可能多的問(wèn)題, 而不是出現(xiàn)第一個(gè)問(wèn)題后構(gòu)建就停止, 這樣的話可以批量修復(fù)它們?nèi)缓笤僦匦逻\(yùn)行一次構(gòu)建, 而不是一遍一遍的運(yùn)行構(gòu)建來(lái)逐個(gè)找出錯(cuò)誤

    1. 可以用一些任務(wù)提供的 haltonerror, haltonfailure, errorproperty 等來(lái)控制構(gòu)建結(jié)束的時(shí)機(jī)和最后的結(jié)果, 如:

        <junit haltonerror="false" haltonfailure="false" errorProperty="test.failed" failureProperty="test.failed" ...>
            <!-- ... -->
        </junit>
        <fail if="test.failed">Tests failed.  Check log or reports for details</fail> 

    4. 需要在不同操作系統(tǒng)上運(yùn)行

    1. 利用 <exec> 的 os 或 osfamily 屬性來(lái)控制不同操作系統(tǒng)上的行為

    2. 路徑分隔符統(tǒng)一使用 "/"

    5. 需要在不同團(tuán)隊(duì)成員的機(jī)器上運(yùn)行, 每個(gè)人環(huán)境都不一樣

    其實(shí)這是配置管理的問(wèn)題, 項(xiàng)目的所有文檔和依賴, 甚至包括Ant本身都應(yīng)該包含在一個(gè)單根目錄下, 并且Check in到版本控制系統(tǒng)中. 里面所有涉及路徑的地方都使用相對(duì)路徑. 這樣項(xiàng)目就可以即拷即用

    但總有一些對(duì)外部環(huán)境的依賴, 這是就要借助 Ant 強(qiáng)大而合理的 immutable property 體系

    1. 所有可能變化的地方都使用 property 來(lái)引用

    2. 優(yōu)先使用 JVM 的系統(tǒng)屬性, 而不是環(huán)境變量

    3. 使用 user.properties 文件定義環(huán)境相關(guān)的property, 并在構(gòu)建腳本中最先引入 <property file="${user.home}/user.properties" />

    4. 在引入 user.properties 之后, 為所有屬性定義合理的缺省值, 以處理 user.properties 不存在不完整的情況

    5. 后面兩步也可以用 <propertyfile> 來(lái)代替

    一個(gè)應(yīng)用就是可以在命令行傳入用戶名和密碼而不是把它們寫在腳本中, 這樣就避免了安全和隱私問(wèn)題

    其它的例子包括用 property 來(lái)定義 test filter, 或者來(lái)定義碰到第一次錯(cuò)誤是退出還是繼續(xù)運(yùn)行構(gòu)建等

    關(guān)于目錄的處理

    1. 為根目錄定義屬性, 以此為起點(diǎn)定義子目錄的屬性

    2. 總是使用 ${basedir} 作為相對(duì)路徑的前綴. 這樣可以保證即使 Ant 的工作路徑不同, 只要傳遞了正確的 basedir 屬性, 所有的相對(duì)路徑還是正確的.

    3. 使用 location 定義路徑, 而不是 value. Ant會(huì)將 location 展開為絕對(duì)路徑, 這樣即使傳遞到另外的 Ant Project 中, 它的值也不會(huì)變

    6. 由于以上原因, 導(dǎo)致Ant腳本較長(zhǎng)

    Ant不是Script Language, 你更應(yīng)該像編寫產(chǎn)品代碼一樣認(rèn)真對(duì)待它的編寫風(fēng)格

    1. 前面說(shuō)過(guò)通過(guò)命令行參數(shù)控制執(zhí)行的target, 參數(shù)多了, 就要有 Usage, Help

        <target name="usage">
            <echo message="  Execute 'ant a' for a."/>
            <echo message="  Execute 'ant b' for b."/>
            <echo message="  Execute 'ant -Dtest.filter=**/*SeleniumTest.class' for specific test cases."/>
            <echo message="  Execute 'ant -Dsome.property=xxx' for xxx."/>
        </target> 
        <target name="help" depends="usage"/> 
    1. 模塊化構(gòu)建腳本, 使用 <macrodef>

    2. 抽取可復(fù)用的 macrodef 或 target 到單獨(dú)的腳本中, 并在其它腳本中 import 這個(gè)可復(fù)用的文件, 這樣有助于分離關(guān)注點(diǎn), 使腳本更易維護(hù)

    借助第三方工具來(lái)彌補(bǔ)Ant的局限

    1. 缺乏異常處理機(jī)制, 任何 BuildException 都會(huì)終止 Ant 的執(zhí)行, 而任何 Task 都可能出現(xiàn)異常, 這樣有些清理操作就得不到執(zhí)行. 解決方案:

      a. Ant-Contrib的 <trycatch>

      b. CruiseControl 的 AntPublisher. CruiseControl定義了構(gòu)建結(jié)束后的操作, 參見 <<CruiseControl Enterprise 最佳實(shí)踐 (1) : Publish with a Publisher>>

    2. 缺乏依賴管理機(jī)制

      前面已經(jīng)提到, 借助 ivy 來(lái)管理, ivy 已經(jīng)成為了 Ant 的子項(xiàng)目

    其它一些常用的風(fēng)格

    1. Define tasks, datatypes, and properties before targets.

    2. Order attributes logically and consistently.

    3. Separate words in target names with a hyphen.

    4. Separate words with a dot (.) character in property names.

    5. Include an "all" target that builds it all.

    6. Define reusable paths.

    7. Use explicit classpaths wherever possible.

    8. Provide visual and XML test results. Use <formatter type="brief" usefile="false"/> , <formatter type="xml"/> and <junitreport>.

    9. 用以連字符(-)開頭的target名字來(lái)定義無(wú)法從命令行調(diào)用的"內(nèi)部"target

    其它一些常用的技巧

    1. 與用戶交互, 這在持續(xù)集成環(huán)境中應(yīng)該不多: <input>

    2. 并發(fā)執(zhí)行: <parallel>, 通常用來(lái)執(zhí)行在后臺(tái)運(yùn)行的任務(wù)

    3. 遞歸的property定義. Ant 缺省并不支持 property 的遞歸展開, 如 ${${os}.${prop}}. 但任何事情都可以用一個(gè)額外的中間層解決, 這里可以借用的機(jī)制是 <macrodef>

    Here is the macro (along lines suggested by Peter Reilly with reference to http://ant.apache.org/faq.html#propertyvalue-as-name-for-property:

    <!-- Allows you define a new property with a value of ${${a}.${b}} which can't be done by the Property task alone.  -->
    <macrodef name="dymanic-property">
        <attribute name="name"/>
        <attribute name="prop"/>
        <attribute name="os"/>
        <sequential>
            <property name="@{name}" value="${@{os}.@{prop}}"/>
        </sequential>
    </macrodef>

    這樣就可以動(dòng)態(tài)的定義屬性

    <macro.compose-property name="some.property" prop="${component} os="${targetOS}"/>

    <do-something-with property="${some.property}"/>

    詭異的地方

    1. spawn, 不要使用spawn=true, 使用前面的<parallel>

      缺省spawn等于false, 這種情況下Ant退出時(shí)會(huì)把所有fork的進(jìn)程都?xì)⒌? 把spawn設(shè)置成true可以令進(jìn)程壽命長(zhǎng)于Ant, 從而可以不堵塞Ant的執(zhí)行而用來(lái)運(yùn)行后臺(tái)程序. 但會(huì)帶來(lái)很多不好的地方,比如不能即時(shí)在console看到信息等. 并且壽命長(zhǎng)于 Ant 在某些情況下不是我們期待的, 比如在 CruiseControl 的環(huán)境中運(yùn)行 Ant, 如果Ant fork的進(jìn)程沒有隨著Ant退出而退出, 那么CruiseControl會(huì)認(rèn)為Ant進(jìn)程還沒有結(jié)束, 從而一直在那里等待而不是執(zhí)行后面的 Publishers.

      <parallel>的<daemon>來(lái)運(yùn)行后臺(tái)程序

    2. unix上的通配符 (Windows上沒問(wèn)題): On Unix-like systems, wildcards are understood by shell intepreters, not by individual binary executables as /usr/bin/ls or shell scripts.

      <target name="list">
          <exec executable="sh">
          <arg value="-c"/>
          <arg value="ls /path/to/some/xml/files/*.xml"/>
          </exec>
      </target>
    3. 幾個(gè)沒在 jdk 文檔中說(shuō)明的系統(tǒng)屬性? -Duser.country=EN -Duser.language=US

    參考


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 极品美女一级毛片免费| 亚洲色图古典武侠| 日韩在线视频播放免费视频完整版| 免费下载成人电影| 91午夜精品亚洲一区二区三区| 99re视频精品全部免费| 久久精品国产亚洲AV高清热| 久久久久国产精品免费看| 亚洲精品无码不卡| 99久久精品日本一区二区免费| 亚洲午夜久久久久久尤物| 成人av免费电影| 偷自拍亚洲视频在线观看| 亚洲 自拍 另类小说综合图区| 无码免费又爽又高潮喷水的视频| 久久久久亚洲精品无码网址 | 亚洲美女视频免费| 亚洲精品免费在线视频| 老司机亚洲精品影院| 在线精品一卡乱码免费| 亚洲国产无线乱码在线观看| 国产免费av片在线无码免费看| 成人在线免费视频| 亚洲国产人成网站在线电影动漫| 最近高清中文字幕免费| 亚洲s码欧洲m码吹潮| 亚洲人成人网站在线观看| 国产婷婷成人久久Av免费高清| 亚洲综合一区二区| 全免费一级午夜毛片| 日本特黄特色AAA大片免费| 久久精品国产亚洲综合色| 黄色永久免费网站| 免费人成又黄又爽的视频在线电影| 国产亚洲精久久久久久无码77777 国产亚洲精品成人AA片新蒲金 | 国产免费人成视频在线观看 | 精品久久8x国产免费观看| 亚洲色成人网站WWW永久四虎| 亚洲精品无码99在线观看| 99re在线这里只有精品免费| 亚洲精品无码一区二区|