<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)航:
     
    主站蜘蛛池模板: 男人扒开添女人下部免费视频| 天堂亚洲免费视频| h视频在线观看免费| 亚洲另类无码专区首页| 亚洲婷婷综合色高清在线| 亚洲男同帅GAY片在线观看| 日本久久久免费高清| 日本精品人妻无码免费大全| a级片免费在线观看| 免费无码国产V片在线观看| 亚洲永久网址在线观看| 亚洲av成人一区二区三区| 亚洲第一区香蕉_国产a| 亚洲人成精品久久久久| 中文字幕日韩亚洲| 亚洲毛片av日韩av无码| 四虎1515hm免费国产| 国产青草视频免费观看97| 午夜一区二区免费视频| 无码国产精品久久一区免费| 69影院毛片免费观看视频在线 | 亚洲国产综合精品一区在线播放| 在线看片人成视频免费无遮挡| 国产在线观看片a免费观看| 18以下岁毛片在免费播放| 99爱在线精品视频免费观看9| 久久精品免费视频观看| 成人网站免费看黄A站视频| a级毛片免费观看视频| a在线视频免费观看| 日本不卡免费新一区二区三区 | 78成人精品电影在线播放日韩精品电影一区亚洲 | 久久久久久成人毛片免费看| 精品免费tv久久久久久久| 久久亚洲免费视频| 久久久久高潮毛片免费全部播放| 日韩免费人妻AV无码专区蜜桃| 免费看又黄又无码的网站| 18pao国产成视频永久免费| 国产成人精品免费视频动漫 | 亚洲sss综合天堂久久久|