本文是實戰每晚構建系列的第三篇,利用第二篇文章中敘述的開源技術對第一篇中的分析模型進行設計和實現。
1、構建信息顯示系統的設計
這是一個典型的web應用系統,不過非常簡單。根據《面向對象的系統分析和設計》所描述的,設計主要對四個部分進行描述:
問題域的細化:考慮將來實現語言的特性和利用某些設計模式,對分析模型進行細化,並作某些權衡。實現對未來系統"如何做事情"的描述。
人機界面設計:考慮和使用者的交互,對信息顯示的布局和接收用戶指令或數據的行為進行設計。
存儲設計:考慮如何保存業務數據,主要考慮現在的存儲方式,同時也要考慮未來存儲方式的可能變化,即業務對象和存儲方式的耦合性問題。
系統接口設計:主要考慮本系統和外在系統之間的合作協議,特別是不要忘了和操作系統或驅動程序的接口。
1.1 分析模型的細化
我們在分析模型中沒有考慮實現的問題,現在我們必須細化構建信息顯示系統的分析模型,使之達到可實現之地步。
根據前面velocity模版系統地介紹,我們擴充一下顯示系統的類圖。如下面的"顯示系統設計類圖"可知,由於Java語言不支持多繼承,而且原來分析模型的BuildInfoLog類只有成員變量,我們把這個類改變成Java語言當中的接口來實現,我們把NightlyBuild變成了實現這個接口的一個類,因此同樣擁有BuildInfoLog的數據成員。另外NightlyBuild還繼承了Java.util.Hashtable類,使得其表現為一個哈西表,這個哈西表以項目的名字為Key,以該項目的構建標簽列表為值。根據MVC模式的精神,NightlyBuild類是個業務對象類,應該從信息顯示的格式化功能中解放出來,所以NightlyBuild類原來的list_ Buildinfo_table方法放到buildinfo_list.vm模版文件中實現。同時我們增加了一個NightlyBuildServlet類來響應構建信息關心者的訪問需求,它是velocity中VelocityServlet類的子類,因此NightlyBuildServlet任MVC模式中的控制角色。
在下面的"顯示系統MVC視圖"中可以看出,業務對象NightlyBuild對象以nightlyBuild的名字保存在模型context中,當控制NightlybuildServlet用模版文件buildinfo_list.vm來滿足構建信息關心者浏覽構建信息目錄的要求時,buildinfo_list.vm文件格式化保存在context中的NightlyBuild對象的信息並形成視圖供浏覽者浏覽。
1.2 人機界面設計
人機界面設計就是設計浏覽者和系統交互的方式,以及系統展示信息的布局。構建信息顯示系統是個典型的web應用,浏覽者首先在其浏覽器中輸入構建信息顯示系統的URL,系統就會把構建信息目錄顯示給浏覽者,浏覽者通過點擊構建信息目錄頁面上的超鏈就可以訪問相應的信息。我們前面說過每個構建信息會在浏覽器中自己顯示自己,所以現在的任務就是設計構建信息目錄顯示頁面。
下面的圖就是構建信息目錄顯示頁面,其中${key}表示某個項目的名字,${nightly_build_tag}為某個項目某次構建的標簽。
管理日志超鏈的url為${logTopDir}/
構建日志超鏈的url為${projectLogTopDir}/${nightly_build_tag}.txt
度量信息超鏈的url為${logTopDir}/${nightly_build_tag}
測試記錄超鏈的url為${testTopDir}/${nightly_build_tag}
覆蓋率超鏈的url為${testCoverTopDir}/${nightly_build_tag}
產品超鏈的url為${distTopDir}/${nightly_build_tag}
每晚構建平台
${key}
構建序列 構建日志 構建日志 度量信息 測試記錄 覆蓋率 產品
1 管理日志 構建日志 度量信息 測試記錄 覆蓋率 產品
2
...
${key}
構建序列 構建日志 構建日志 度量信息 測試記錄 覆蓋率 產品
1 管理日志 構建日志 度量信息 測試記錄 覆蓋率 產品
2
...
1.3 存儲設計
存儲設計主要是指數據庫的設計或者文件格式的設計,構建信息顯示系統使用文件系統作為存儲目標。構建信息顯示系統的存儲設計主要工作是定義分析模型中BuildInfoDir類也就是設計模型中BuildInfoDir接口的變量的值和格式。
1.3.1 BuildInfoDir接口
類名/接口名 構建信息存放位置接口 類英文名 BuildInfoDir
成員變量
變量名 變量說明 缺省值或值
webAppDir 是應用服務器存放web應用程序的根目錄,這個值根據系統安裝而定。
nightlyWebAppName 構建信息顯示系統web應用程序的名字,同變量webAppDir一起構成了構建信息顯示系統應用程序的根目錄。 "nightlybuild"
nightly_Build_Tags 保存所有的構建標簽,是構建信息顯示系統web應用程序根目錄下的一個文件的名字。 "nightBuildLog"
logTopDir 相對於顯示系統應用程序的根目錄下的一個目錄名,保存構建管理服務運行的日志的目錄 "adminLogs"
statCVSTopDir 相對於顯示系統應用程序的根目錄下的一個目錄名,保存了所有應用項目的項目度量結果的頂層路徑 "statCVSes"
projectLogTopDir 相對於顯示系統應用程序的根目錄下的一個目錄名,保存了所有應用項目構建服務實例運行日志的頂層路徑 "projectLogs"
testCoverTopDir 相對於顯示系統應用程序的根目錄下的一個目錄名,保存了所有應用項目的測試覆蓋率計算結果的頂層路徑 "testCovers"
distTopDir 保存了所有應用項目的發布版的頂層路徑,值和變量webAppDir相同
testTopDir 相對於顯示系統應用程序的根目錄下的一個目錄名,保存了所有應用項目的測試結果的頂層路徑 "tests"
下面是nightly_Build_Tags所指的文件格式:
每行包括一個項目構建標簽,構建標簽的格式為項目名-yyyymmdd_HHMMSS的格式
比如可能的文件內容如下:
nightlybuild-20030312_080100
cover-20030312_080100
nightlybuild -20030312_080100
cover-20030313_080100
這個文件內容表示:兩個項目分別為nightlybuild和cover,他們在2003年3月12日和13日的早上8點1分得到了構建。
1.4 系統接口設計
系統接口設計主要描述被設計的系統與外界系統特別是操作系統的接口的設計和描述。構建信息顯示系統和構建系統的接口就是存儲設計中的BuildInfoDir接口,和操作系統無接口。
2、構建系統的設計
2.1 分析模型設計
考慮到ant腳本的局限性,我們對構建系統分析模型作如下調整:
因為OSScheduler是個操作系統定時服務的腳本或配置,所以無法繼承BuildInfoLog類,我們增加一個LogAdmin類用來啟動和記錄BuildAdmin運行的日志。為什麼我們必須在OSScheduler和BuildAdmin中插入一個LogAdmin類?這是因為ant腳本無法自己記錄自己的輸出,必須靠調用者,我們必須使用<ant>任務來運行和記錄另外一個類的輸出。同樣BuildAdmin會用<ant>任務來運行和記錄ProjectBuild的輸出日志。
LogAdmin用<ant>任務實現對BuildAdmin的單項聯系;至於BuildAdmin和ProjectBuild之間的一對多的關系可用多個<ant>任務實現。由於要運行,所以類LogAdmin,BuildAdmin和ProjectBuild都必須是可運行的(runnable)。
一個項目的構建應該可以分成固定不變的腳本和項目相關腳本兩部分,這個需求可以和設計模式中的模版方法模式的目的相吻合。
類ProjectBuild的test_project方法要完成下列步驟:
准備測試環境,包括為測試目的而進行的編譯、打包、安裝,其中編譯和打包與具體項目有關;
測試,這個任務與具體項目有關;
生成測試報告,它與項目無關;
生成覆蓋率信息,它也與項目無關。
類ProjectBuild的dist_project方法要完成的步驟有編譯、打包和安裝,安裝與項目無關。這樣運用了模版方法模式之後,構建系統的設計類圖就變成了構建系統設計類圖二所示。
下面的序列圖顯示了模版方法調用抽象方法的序列:
步驟1.1針對每個被管理的應用項目調用步驟1.1.1;
步驟1.1.1.4.1 test_project是個模版方法,compile(),compiletestcases(),test_war(),test()是子類ProjectBuild要實現的方法;
步驟1.1.1.4.2 dist_project是個模版方法,compile(),dist_war()是子類ProjectBuild要實現的方法。