【 tulaoshi.com - 编程语言 】
本文是实战每晚构建系列的第三篇,利用第二篇文章中叙述的开源技术对第一篇中的分析模型进行设计和实现。
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要实现的方法。