1、2018年6月9日星期六,第1页,第9章 软件测试,软件测试是软件工程的一个重要环节,相当于工程领域中的质量检验部分,是确保软件工程质量的重要手段。简单地说,软件测试就是为了发现错误而执行程序的过程。在IEEE(美国电气和电子工程师协会)提出的软件工程标准术语中,软件测试被定义为:“使用人工和自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清楚预期结果与实际结果之间的差别。”软件测试是与软件质量密切联系在一起的,归根到底,软件测试是为了保证软件质量。,2018年6月9日星期六,第2页,第9章 软件测试,9.1 基本概念9.2 测试方法9.3 测试过程,9.1.1 软件
2、测试的必要性9.1.2 软件测试目的9.1.3 软件缺陷定义9.1.4 测试用例9.1.5 软件测试的原则,9.1.1 软件测试的必要性,1. 问题引入根据统计表明,软件测试的工作量往往占软件开发总工作量的40%以上,可能我们会思考这样一个问题,花费那么多资源在测试上,花费在一个对整个软件工程“没有任何建设成果”的活动上,值得吗?,2. 解答问题事实上,答案是肯定的。软件缺陷和故障问题在某些情况下会造成相当严重的损失和灾难,花费大量的资源在测试上,目的是为了提高软件质量,尽可能地减少软件缺陷造成的损失。,3. 分析问题让我们先来了解几个“著名”的计算机工程事故吧,借此说明软件缺陷和故障问题有时
3、会造成相当严重的损失和灾难。,(1) 2007年5月18日,国内大量用户的电脑集体出现问题:开机后自动重启、蓝屏,屏幕上显示unknown hard error的字样,安全模式下也无法正常进入系统等等。用户的第一反应就是感染了病毒,而在经过金山毒霸反病毒专家的仔细分析后,发现了问题的症结所在:诺顿杀毒软件的误报所致,赛门铁克SAV 2007-5-17 Rev 18版本的病毒定义码中,将Windows XP操作系统的netapi32.dll文件和lsasrc.dll文件判定为Backdoor.Haxdoor病毒,并进行隔离,导致重启电脑后无法进入系统,并出现蓝屏、重启等现象,造成了大量的数据丢失
4、,系统崩溃,损失惨重。,此次电脑病毒误报事件被反病毒专家称为是近5年来国内影响面最大的误报事件。诺顿在企业级用户中占据了30%的份额,这次低级的错误造成了大量的电脑系统崩溃,造成了巨大的损失,虽然,赛门铁克已经公开道歉,修复了Bug,并提出了拯救系统的方案,但是,赛门铁克还是很可能面临着巨额的索赔。其实,针对类似很多的“误杀门”事件,软件厂商只需在软件发布前做一个完整的兼容性测试就可以很有效地避免这样的灾难事故了。,(2) 2000年12月4日上午10时30分起,浦东地区不少电话用户突然发现通话受阻,一部分移动电话、寻呼机用户也受到影响,无法正常收发信息。由于故障地区位于浦东中心地区,大量中外
5、商务机构包括证券大厦、期货交易所等都在其中,造成了严重的局面。经电信部门紧急查寻,发现问题出在一电话汇接局内的贝尔电话交换机上,估计是软件系统发生故障。上海有关部门立即调集了一批电信专家和技术人员来到现场,与上海贝尔公司派出的专家一起进行“会诊”和抢修。通话受阻情况在当晚午夜得到平息。,最终,上海电信部门确认了交换机软件的缺陷是造成这次事件的主要原因。虽然这一系统7年前就已经安装在汇接局,并一直没有被发现有缺陷。但有关专家认为,如果多种作用因素同时出现,或者是瞬间出现极高的话务量,这一缺陷迟早会“现身”。,(3) 1999年12月3日,美国航天局的火星极地登陆飞船在试图登陆火星表面时失踪了,造
6、成了巨大的损失。错误修正委员会观测到故障,并确定出现误动作的原因极可能是由于某一数据位被意外地更改了。大家对这一错误感到非常震惊,认为该问题应该在内部测试时就予以解决。,2018年6月9日星期六,第12页,9.1.2 软件测试目的,1. 问题引入软件测试是必要的,那么,软件测试的目的是什么呢?难道花费那么多资源用在测试上,仅仅是为了证明软件是错误的吗?,2018年6月9日星期六,第13页,8.1 业务架构,2. 解答问题随着软件系统的规模和复杂性与日俱增,软件的生产成本和软件中存在的缺陷和故障造成的各类损失也大大增加,甚至会带来灾难性的后果。软件质量问题已成为所有使用软件和开发软件的人关注的焦
7、点,从大量的事实已经证实了软件测试的必要性。,2018年6月9日星期六,第14页,8.1 业务架构,3. 分析问题 在表面看来,软件测试的目的与软件工程其他阶段的目的好像是相反的,软件工程其他阶段都是在“建设”的,简单说,软件工程师一开始就力图从抽象的概念出发,然后逐步设计出具体的软件系统,直到用一种适当的程序设计语言编写、生成可执行的程序;然而,在测试阶段,测试人员所做的却是努力设计出一系列的测试方案,不遗余力地“破坏”已经建造好的软件系统,竭力证明程序中有错误,程序不能按照预定要求正确工作。,可以很肯定地说,这只是表面现象,暴露问题、“破坏”程序并不是软件测试的最终目的,软件测试的目的是尽
8、早发现软件缺陷,并确保其得以修复。换而言之,软件测试的最终目的是提高软件质量。所以,软件测试表面看起来是“破坏”,其实质却是为了“建设”质量更高的软件产品。用一句不太恰当的话总结就是,破而后立。,2018年6月9日星期六,第16页,9.1.3 软件缺陷定义,1. 问题引入一直在说软件缺陷,那么,如何定义软件缺陷呢?错误等同于缺陷吗?,2018年6月9日星期六,第17页,8.2.1 客户服务系统业务架构分析,2. 解答问题(1) 这是一个难以回答的问题。由于软件开发公司的文化和用于开发软件的过程不同,造成了用于描述软件故障、软件失败的术语有很多,比如说,缺点(defect)、偏差(varianc
9、e)、谬误(fault)、 失败(failure)、问题(problem)、矛盾(inconsistency)、错误(error)、毛病(incident)、异常(anomaly)、缺陷(bug)等等。,8.2.1 客户服务系统业务架构分析,(2) 不过,一般来说,我们习惯上把所有的软件问题都统称为缺陷(bug)。要定义软件缺陷,我们必须先了解另一个概念产品需求规格说明书(又称需求说明书):是软件开发小组的协定,它对开发的产品进行定义,包括产品有何细节、如何操作、功能如何、有何限制等。,(3) 软件缺陷的正式定义如下,只要符合下列5个规则中的任何一条都是软件缺陷:软件未达到产品说明书表明的功能
10、;软件出现了产品说明书指明不会出现的错误;软件功能超出了产品说明书指明的范围;软件未达到产品说明书虽未指出但应达到的目标;软件测试员认为软件难以理解、不易使用、运行速度缓慢,或者最终用户认为不好。,2018年6月9日星期六,第20页,8.2.1 客户服务系统业务架构分析,3. 分析问题(1) 比如说,日常使用的计算机的产品需求规格说明书一般描述如下:计算器通过用户输入要计算的数字,能准确地完成加、减、乘、除的数学运算,并在显示屏上准确显示计算的结果。在任何时候计算机都不会出现显示错误结果的情况,不会出现“死机”无响应的情况,不会出现崩溃无法恢复的情况。,8.2.1 客户服务系统业务架构分析,(
11、2) 假设,测试员发现,按要求输入了两个数字1和2,并且按下了“+”键,要求进行加法数学运算,但是,最终计算器并没有在显示屏上显示结果,又或者是计算器在显示屏上显示的是错误的结果,比如显示结果是4,而不是正确结果3。那么,根据第1条规则,这就是一个软件缺陷。,假设,测试员对计算器的键盘随意敲击(猴子测试),发现计算器“死机”了,对任何操作都无响应,那么,根据第2条规则,这就是一个软件缺陷。假设,测试员发现,计算机除了能够进行加、减、乘、除的数学运算,还能够进行sin、cos等科学运算,虽然,运算处理的结果是正确的,但是,根据第3条规则,这就是一个软件缺陷。因为,很可能这个计算器就是为小学的学生
12、开发的,而加入这样的科学运算会造成小学生学习混乱。,假设,测试员发现,计算器在电池电力不足的情况下,会丢失运算处理后显示的结果,那么,根据第4条规则,这就是一个软件缺陷。假设,测试员和最终的用户都认为,计算器的按键太小了、按键间距太密了、按键上的数字和运算符号显示不清晰,那么,根据第5条规则,这些都算是一个软件缺陷。,2018年6月9日星期六,第24页,9.1.4测试用例,1. 问题引入在整个测试过程中,测试用例可以说是整个软件测试过程的核心,那么,什么是测试用例呢?,2018年6月9日星期六,第25页,8.2.2 客户服务系统子模块划分,2. 解答问题所谓测试用例是为了特定的目的而设计的一组
13、测试输入、执行步骤和预期结果,以便测试某个程序路径或核实是否满足某个特定需求。测试用例是执行测试的最小实体。测试用例设计就是将软件测试的行为活动作为一个科学化的组织活动,软件测试是有组织性、步骤性和计划性的,而设计软件测试用例的目的就是为了能将软件测试的行为转换为可管理的模式。,8.2.2 客户服务系统子模块划分,3. 分析问题(1) 测试用例对整个软件测试过程非常重要,原因有以下几方面:测试用例构成了设计和制定测试过程的基础;测试的“深度”与测试用例的数量成比例,由于每个测试用例反映不同的场景、条件或经由产品的事件流,因而,随着测试用例数量的增加,您对产品质量和测试流程也就越有信心;判断测试
14、是否完全的一个主要评测方法是基于需求的覆盖,而这又是以确定、实施和执行的测试用例的数量为依据的,类似下面这样的说明:“95%的关键测试用例已得以执行和验证”,远比“我们已完成95%的测试”更有意义;测试工作量与测试用例的数量成比例,根据全面且细化的测试用例,可以更准确地估计测试周期各连续阶段的时间安排。,8.2.2 客户服务系统子模块划分,(2) 如果一个测试用例用于证明某个需求已经满足,通常称作正面测试用例;如果一个测试用例反映某个无法接受、反常或意外的条件或数据,用于论证只有在所需条件下才能够满足这个需求,这样的测试用例称作负面测试用例。,8.2.2 客户服务系统子模块划分,(3) 不同类
15、别的软件,其测试用例是不同的。测试用例通常根据它们所关联关系的测试类型或测试需求来分类。不同的测试用例,其内容可能包括测试目标、测试环境、输入数据、测试步骤、预期结果、测试脚本等等,并形成文档。但是,不管是哪一种类型的测试用例,其核心的三个部分:测试输入、执行步骤和预期结果,是绝对不会少的。,8.2.2 客户服务系统子模块划分,(4) 测试用例是测试工作的指导,是软件测试必须遵守的准则,更是软件测试质量稳定的根本保障。在软件测试过程中,最佳的方案还是为每个子测试需求编制两个以上或者更多的测试用例。,9.1.5 软件测试的原则,1. 问题引入为了达到软件测试的目标,在软件测试过程中针对测试计划、
16、测试用例设计以及测试管理必须遵循哪些基本原则?,2018年6月9日星期六,第31页,8.2.2 客户服务系统子模块划分,2. 解答问题为了避免走弯路,为了迅速地进入软件测试的殿堂,在这里列举8条测试原则,它们可以理解为是软件测试领域的公理,是软件测试领域的“交通法则”。完全测试软件是不可能的软件测试是有风险的行为测试无法显示潜在的软件缺陷软件缺陷的群集现象软件缺陷的免疫现象随着时间的推移,软件缺陷的修复费用将呈几何级数增长“零缺陷”是不切实际的行为尽量避免测试的随意性,2018年6月9日星期六,第32页,8.2.2 客户服务系统子模块划分,3. 分析问题(1) 完全测试软件是不可能的想要进行完
17、全的测试,在有限的时间和资源条件下,找出所有的软件缺陷和错误,使软件趋于完美,那是不可能的。,例如,要完全测试计算器软件的加法运算,那么,测试员就要构造测试输入,尝试测试1+1,显示屏显示结果是2,实际结果正确;然而,测试员能否根据前面的测试就很肯定地说,进行1+2运算,计算器显示的结果不会出错呢?没有100%的把握,所以,测试员还是要构造这样的测试输入,进行1+2运算,就算1+2的结果正确,那么1+3呢,1+4呢?1+999999999999999999999999999999999呢?如果在字长32位的计算机上运行,假设只进行整数相加运算,那么按照穷举法,测试数据有232232=264个,
18、如果测试一组数据需要1毫秒,一年工作36524小时,要完全测试这些数据需要5亿年的时间。,8.2.2 客户服务系统子模块划分,在实际测试中,完全测试是不可行的,即使最简单的程序也不行,主要有以下4个原因:输入量太大;输出结果太多;路径组合太多;软件需求规格说明书很可能也没有客观的标准,从不同的角度看,软件缺陷的标准不同。,当然,完全测试是不可能的,那是否就要放弃测试呢?不是的,依据一定的测试方法指导,进行相应等价类的划分等手段,是可以在时间和资源可控的范围内,进行有限测试,却能够发现软件绝大部分的缺陷,使软件的质量达到用户要求的范围。,8.2.2 客户服务系统子模块划分,(2) 软件测试是有风
19、险的行为如果放弃了完全测试,选择了不测试所有的情况,那么,我们就选择了风险。比如在计算器的例子中,测试员已经对加法运算进行了有限的测试,但是,测试员在这有限的测试里,并没有测试输入1024+1024的情况,那么,用户在用到这组数据进行相加时,就是存在风险的,软件可能会出错。,也就是说,如果没有办法完全测试,那么,软件就有可能还存在着缺陷。如果试图测试所有的情况,那么测试费用将是超大幅度地增加,而软件缺陷发现的数量跟费用却不是成正比的,越到后面数量越少;反过来,如果超大幅度地减少测试,那么测试费用也会变得很低,但是却会漏掉大量的软件缺陷。,8.2.2 客户服务系统子模块划分,图9-1 测试量与遗
20、留的缺陷数量之间的关系,(3) 测试无法显示潜在的软件缺陷软件测试员的工作就像防疫员一样,如果在对马匹进行检疫时发现了寄生虫,那么,检疫员可以很放心地说,马匹有病害问题。但是,如果在对马匹进行检疫时没有发现寄生虫的征兆,那么,检疫员可以很确定地保证,马匹没有病害问题吗?答案是否定的,检疫的结果只是表明了依据当前的设备、技术环境,暂时尚未发现寄生虫。但是,很难保证,在更精确的设备、更优良的技术环境下,不会发现寄生虫。,同理,测试只能证明软件存在错误而不能证明软件没有错误,测试无法显示潜在的错误和缺陷,继续进一步测试可能还会找到其它错误和缺陷。如果随意就回答,“经过测试证明软件是没有缺陷的”,那是
21、非常不负责任的行为。,(4) 软件缺陷的群集现象就像寄生虫一样,软件缺陷也会出现群集现象,往往缺陷也很喜欢聚集在一起发生。如果某个模块发现了缺陷,那么根据经验表明,这个模块很可能还存在着更多的缺陷,如图9-2所示。例如,美国IBM公司的OS/370操作系统中,47%的错误仅与该系统的4%的程序模块有关。,图9-2 软件缺陷的群集现象,软件缺陷的群集现象符合Pareto原则(80/20原则):软件测试发现的错误的80,很可能来源于程序模块中的20。其中的问题很可能是以下情况造成的:前置逻辑错误,造成依此为基础的程序代码都产生了错误;程序员的疲劳,造成大量代码坏块;程序员往往会犯同样的错误,因为大
22、部分代码都是复制、粘贴而来;软件的基础构架问题,有些软件的底层支撑系统因为“年久失修”变得越来越力不从心了。,所以,这要求测试员一旦发现某个模块的缺陷有群集的迹象,那么,就应该对这些缺陷群集的模块进行更多的测试和回归验证。,(5) 软件缺陷的免疫现象1990年Boris Beizer在Software Testing Techniques一书中曾经很生动地将软件缺陷的免疫现象描述为“杀虫剂现象”,农民用固定一种农药来杀虫,那么,害虫经过优胜劣汰后,生存下来的害虫就会对这种农药有抵抗力,最后这种农药对害虫就丧失了杀灭作用。,软件缺陷也有类似的免疫现象,如果测试员总是用固定的测试用例来检测软件缺陷
23、,那么,很可能会发现这样的现象,第一次检测会发现较多的缺陷,其次再做检测发现的缺陷越来越少,最终再做检测就不能发现缺陷了。,所以,这要求软件测试员在测试过程中不断地完善测试用例,变换各种测试方法、测试手段设计更多的测试用例,对软件进行测试,从而避免软件缺陷的免疫现象。,(6) 随着时间的推移,软件缺陷的修复费用将呈几何级数增长如果1999年美国航天局的火星极地登陆飞船在产品需求说明书中就明确表述在飞船降落时有强烈的机械震动,那么,在设计飞船降落系统时就会做得更严谨一些,从而可以用很少的费用就可以避免飞船坠毁导致上十亿美元的损失。软件开发的过程可以分为这几个阶段:风险调查、需求分析、概要设计、详
24、细设计、编码、测试、验收、运行与维护阶段。而软件缺陷的修复费用会随着时间的推移,呈几何级数增长,如图9-3所示。,图9-3 软件修复费用呈金字塔模型,如果在需求分析阶段产生了缺陷,在设计阶段之前就被发现了,那么,修复的费用将会很少,就仅仅是重新修改需求说明书就可以了;如果在需求分析阶段产生了缺陷,在之后的设计、编码、测试、验收阶段一直都没有被发现,等到软件已经在用户实际环境运行了才被用户发现,并且软件的缺陷已经给用户造成了实际损失,那么,要修复这个缺陷的费用就非常庞大,甚至还要赔偿用户高额的损失费,这是灾难性的后果。所以,应当把“应尽早地介入测试,而且越早越好”作为软件测试者的座右铭。,(7)
25、 “零缺陷”是不切实际的行为“零缺陷”是理想的追求,但是,事实上却是并非所有的软件缺陷都需要修复的,Good-Enough是现实的原则。这要求软件测试员有较高的素质进行良好的判断,搞清楚在什么情况下不能追求完美。项目小组需要进行取舍,根据风险决定哪些缺陷需要修复,哪些不需要修复。,不需要修复软件缺陷的原因有几个:没有足够的时间;不是真正的软件缺陷:很多情况下,在个别人群中被认为是软件的缺陷,但在另一部分人群中却被认为是软件的实用功能,个体对软件理解的不同、需求规格说明书的变更等等都会导致这种情况出现;修复的风险太大:软件本身是脆弱的、难以理清头绪,有点像一团乱麻,修复一个软件缺陷可能导致其它软
26、件缺陷的出现。不去理睬已知的软件缺陷,以避免造成新的、未知的缺陷的做法也许是安全之道;不值得修复:虽然有些不中听,但是事实。在权衡利弊之后,不常出现的软件缺陷和在不常用功能中出现的软件缺陷是可以放过的,可以躲过和用户有办法预防的软件缺陷通常不用修复。,(8) 尽量避免测试的随意性软件测试是有组织、有计划、有步骤的活动,要严格按照测试计划进行,要避免测试的随意性。如果随意地选择了软件系统的某一个模块来进行测试,或者,仅仅随意地使用了某个单一的测试方法,那么,这根本没办法实现测试的目的。虽然有可能某一模块达到了需求说明书规定的要求,或者,软件中不会出现某一类软件缺陷了,但是,这对软件整体的质量根本
27、无法保障。 事实是,软件的质量评价是符合木桶原理的,木桶能够盛多少水不是依据最高的那块木板,而往往是整个木桶中最低的那块木板决定的。,随着中国软件业的日益壮大和逐步走向成熟,软件测试也在不断发展。从最初的由软件编程人员兼职测试到软件公司组建独立专职测试部门。测试工作也从简单测试演变为包括:编制测试计划、编写测试用例、准备测试数据、编写测试脚本、实施测试、测试评估等多项内容的正规测试。测试方式则由单纯手工测试发展为手工、自动兼之,并有向第三方专业测试公司发展的趋势。软件测试不能仅仅由软件开发人员自己完成,要求有专门的测试人员进行测试,并且还会要求用户、业务领域专家等等来参与,特别是验收测试阶段,
28、用户是测试是否通过的主要评判者。,2018年6月9日星期六,第55页,9.2 测试方法,已经对软件测试有了一定的认识了,那么,怎么样进行软件测试呢?对软件进行的测试是可以依照具体的测试方法来指导的。根据不同的关注重点,软件测试方法主要按以下两种方式来分类:根据软件测试用例的设计方法来分类,软件测试方法可以分为白盒子测试和黑盒子测试;根据软件测试策略和过程来分类,软件测试方法可以分为单元测试、集成测试、确认测试、系统测试、验收测试等等。,9.2.1 白盒子测试9.2.2 黑盒子测试,9.2.1 白盒子测试,1. 问题引入在软件测试中,经常会使用到的方法是白盒子测试方法和黑盒子测试方法,那么,什么
29、是白盒子测试方法呢?常用的白盒子测试方法有哪些呢?,2018年6月9日星期六,第58页,8.3 软件架构,2. 解答问题(1) 在软件测试中,白盒子测试是根据被测程序的内部结构设计测试用例的一种测试方法,又称为结构分析。白盒子测试将被测程序看作一个打开的盒子,测试者能够看到被测程序的源代码,可以分析被测程序的内部结构,此时测试的焦点集中在根据其内部结构设计测试用例。(2) 常用的白盒子测试方法有:数据流分析、逻辑覆盖、路径分析等等。,2018年6月9日星期六,第59页,8.3 软件架构,3. 分析问题一个典型的软件架构包括两个视角:广度视角和深度视角。这两个视角构成对软件架构的“立体”描述。广
30、度视角即是我们常说的软件层次结构,它关注软件的分层,规定每一层的职责以及层与层之间的通讯标准。一般使用包元素来描述。图8-10展示了一个典型的多层架构的层次模型。,8.3 软件架构,图8-10 软件层次的广度视角架构图,8.3 软件架构,另一方面,软件架构还需要描述深度视角。所谓深度视角,是指广度视角中每一层的详细说明,它关注每一层以及每个部分的具体实现架构。例如可以针对业务实体层进行架构描述,也可以针对XMLBean进行架构描述。图8-11展示了业务实体层的深度视角视图。,8.3 软件架构,图8-11 软件层次深度视角架构图,8.3 软件架构,广度视角和深度视角将软件架构立体化了。层次构成了
31、广度视角维度,而每一个层次的包、类的结构构成了深度视角维度。,2018年6月9日星期六,第64页,8.4 软件架构设计,1. 问题引入软件架构设计就是要将我们在业务架构中设计出来的业务构件有机地结合在一起协调工作。那么客户服务系统的软件架构是怎样的呢?,2018年6月9日星期六,第65页,8.4 软件架构设计,2. 解答问题客户服务系统软件架构图如图8-12所示。,2018年6月9日星期六,第66页,图8-12 客户服务系统软件架构图,2018年6月9日星期六,第67页,8.4 软件架构设计,3. 分析问题根据需求,客户服务系统要求是B/S架构的,即浏览器/服务器架构。该架构有许多优点:客户端
32、无需安装任何软件,只要有浏览器就可以使用系统,方便客户服务人员能即时处理客户问题。当业务架构确定后,至于是选用.NET来实现还是选用J2EE来实现并不重要,主要依据开发团队的技术素质而定,以期达到最小项目风险和减少开发成本的目的。本节选用J2EE来描述客户服务系统的软件架构分层模型,采用了MVC架构体系,结合当前使用最成熟的Struts + Spring + Hibernate框架,如图8-13所示。,8.4 软件架构设计,图8-13 Struts+Spring+Hibernate框架图,8.4 软件架构设计,Struts + Spring + Hiberante框架的WEB应用常常被扩展成4
33、个各负其责的层次:表示层(Presentation)、业务层(Business)、持久层(Persistence)、领域模型层(Domain Model)。前三层分别对应于Struts、Spring、Hibernate,而领域模型层则是由那些现实世界中的业务对象组成,如客户、咨询、回访、投诉等等,它们是在上面三个层之间传递的对象。每层职责明确,彼此独立,通过专门编写的接口传递消息。,8.4 软件架构设计,客户服务系统分为四个层次,其中WEB层采用Struts框架,Service和Dao采用Spring框架封装客户服务业务逻辑处理,DB Control层采用Hibernate框架。VO(Valu
34、e Object,值对象)和PO(Persistant Object,持久对象)之间的关系及传递如图8-14所示。,8.4 软件架构设计,图8-14 PO与VO之间实现关系,8.4 软件架构设计,PO可以看成是与数据库中的表相映射的Java对象。一张数据库表对应一个Java对象。由Hibernate自动反转生成,简化Java与数据库之间的操作。VO是由Hibernate PO复合而成的一个业务对象,用于业务层之间的数据传递。RelationShip维护组成VO与多个PO之间的对应关系。Hibernate可维护PO之间的一对多,一对一,多对多等关系,但这些关系是指数据库之间的关系。Relatio
35、nship管理的是非数据库的、业务逻辑要求的关系。ServiceControl是Service层访问Dao层的接口。负责将PO组合成VO或将VO分解成PO。Service层通过ServiceControl来存取VO,同时将分解出的PO传递给DBControl。,8.4 软件架构设计,图8-15以客户服务系统查询客户来电咨询记录,同时显示客户资料信息为例,说明客户服务系统架构层次的动态实现。,图8-15 客户服务系统查询客户来电咨询的动态实现,8.4 软件架构设计,简要说明:客户服务人员首先发出“查询客户咨询记录”命令,系统查找到客户咨询记录相关信息,并返回给ServiceControl,同时根
36、据记录在该表中的客户资料ID的外键信息,到客户资料信息表中查找相关客户资料的详细信息,最后将客户资料信息和客户来电记录信息组合成VO返回到Service层,展示给客户服务人员。,8.4 软件架构设计,下面分别对Struts、Spring和Hibernate作简要介绍。,8.4 软件架构设计,(1) StrutsStruts由一组相互协作的类、Servlet以及丰富的标记库(jsp tag lib)和独立于该框架工作的实用程序类(Validator)组成。Struts有其自己的控制器(Controller),同时整合了其它的一些技术去实现模型层(Model)和视图层(View)。在模型层,Str
37、uts可以很容易地与数据访问技术相结合,包括EJB、JDBC和Object Relation Bridge。在视图层,Struts能够与JSP、Velocity Templates和XSL等等这些表示层组件想结合。Struts Framework是MVC 模式的体现,下面我们就分别从模型、视图和控制来看看Struts的体系结构(Architecture)。Struts Framework的体系结构响应客户请求的时候,各个部分的工作原理如图8-16所示。,8.4 软件架构设计,图8-16 Struts工作原理图,8.4 软件架构设计,(2) SpringSpring 是一个开源框架,是为了解决企
38、业级应用程序开发的复杂性问题而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 Bean 的方式,如图8-17所示。,8.4 软件架构设计,图8-17 Spring框架分层架构图,8.4 软件架构设计,(3) HibernateHibernate是一个免费的开源Java包,它使得与关系数据库打交道变得十分轻松,它是一个面向Java环境的对象/关系数据库映射工具。对象/关系数据库映射(obje
39、ct/relational mappin,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。Hibernate不仅管理Java类到数据库表的映射(包括Java数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和JDBC处理数据的时间。,8.4 软件架构设计,事实上,在一个基于数据库的Web系统中,建立数据库连接的操作将是系统中代价最大的操作之一。很多时候,可能系统的速度瓶颈就在于此。Hibernate的目标是对于开发者通常的数据持久化相关的编程任务,解放其中的95,对于那些在基于Java的中间层应用中
40、,它们实现面向对象的业务模型和商业逻辑的应用,Hibernate是最有用的。不管怎样,Hibernate一定可以帮助我们消除或者包装那些针对特定厂商的SQL代码,并且帮我们把结果集从表格式的表示形式转换到一系列的对象中去。,2018年6月9日星期六,第83页,8.5 软件架构与框架,1. 问题引入现实中,很多人把架构和框架搞混,有的人认为架构和框架就是同一个东西,那么究竟两者是否相同,如果不同,又有什么区别呢?,2018年6月9日星期六,第84页,8.5 软件架构与框架,2. 解答问题架构的英文原文是Architecture,而框架则是Framework。显然是两个完全不同的词。从技术上讲,I
41、T有一个职业是架构师,代表了软件技术人员最高的职业,却从没有听说过有软件框架师的,所以肯定地说,软件架构和软件框架是两回事。架构是一种思想,一个系统蓝图,是对系统高层次的定义和描述。框架是针对某个问题领域的通用解决方案,它通常集成了最佳实践和可复用的基础结构,对开发工作起到减少工作量、指导和规范作用。,2018年6月9日星期六,第85页,8.5 软件架构与框架,3. 分析问题如果用建设一幢大楼来作比喻,架构就是大楼的结构、外观和功能性设计,它需要考虑的问题可以延伸到抗震性能、防火性能、防洪性能等;而框架是建设大楼过程中的一些成熟工艺的应用,例如楼体成型、一次浇灌等。再举一个例子,可以说架构是战
42、略性的,它描述战略目标、指挥系统、信息传递、职责、部署等;框架是战术性的,它描述组织、建设、作战方案、命令下达、战术执行等。我们可以说MVC是一种设计思想,它将应用程序划分为实体、控制和视图三个逻辑部件,因此它是一个软件架构。而Struts,JSF,WEBWork等开源项目则分别以自己的方式实现了这一架构,提供了一个半成品,帮助开发人员迅速地开发一个符合MVC架构的应用程序,因此可以说我们采用了Struts或JSF或WEBWork软件框架,开发出了符合MVC架构的应用程序。,8.6 软件架构的“41”视图模型,1. 问题引入 软件架构用来处理软件高层次结构的设计和实施。它不是一维的,而是由多个
43、同时存在的视图构成。它将若干结构元素进行装配,从而满足系统主要功能和性能需求,并满足其它非功能性需求,如可靠性、可伸缩性、可移植性和可用性等。那么,描述软件架构的这个“41”视图究竟有哪些?它们有怎样的交互作用?,8.6 软件架构的“41”视图模型,2. 解答问题软件架构“41”视图模型及视图间的交互关系如图8-18所示。4个视图为逻辑视图、进程视图、组件视图和部署视图,而用例视图则为“1”的视图。,8.6 软件架构的“41”视图模型,图8-18 软件架构“41”视图模型,8.6 软件架构的“41”视图模型,3. 分析问题在RUP中,软件架构的“41”视图模型包括下列五个视图:(1) 用例视图
44、:包含用例和场景,这些用例和场景含有重要架构行为、类或技术风险。它是用例模型的子集,用于描述用例、参与者和普通设计类的用例图,描述设计对象及其协作的顺序图。(2) 逻辑视图:包含最重要的设计类、包和子系统中类的组织,以及各层中这些包和子系统的组织。它还包含某些用例实现,它是设计模型的子集。逻辑视图包含类图、状态图和对象图。,8.6 软件架构的“41”视图模型,(3) 组件视图:包含实施模型的概述,以及按模块划分为包和层的模型组织。还描述了从“逻辑视图”将包和类分配到“组件视图”中的包和组件。它是组件模型的子集,包含组件图。(4) 进程视图:包含所涉及任务(进程和线程)的描述、任务的交互和配置以
45、及从设计对象和类到任务的分配。仅当系统具有相当并行程度时,才需要使用该视图。它是设计模型的子集,包含类图和对象图。,8.6 软件架构的“41”视图模型,(5) 部署视图:包含对最典型平台配置的多个实际节点的描述,以及从“进程视图”将任务分配到实际节点。仅当系统为分发式系统时,才需要使用该视图,它是部署模型的子集,包含部署图。但对于一些简单的系统,您可以省略其中包含的某些视图。例如,如果只有一个处理器,则可以省略部署图;如果只有一个进程或程序,则可以省略进程视图。,8.7 组件图,1. 问题引入在软件建模过程中,使用用例图可以推断系统希望的行为;使用类图可以描述系统中的词汇;使用顺序图、组件图、
46、状态图和活动图可以说明这些词汇中的事物如何相互作用以完成某些行为。在完成系统的逻辑设计之后,下一步要定义设计的物理实现,在面向对象系统的物理方面进行建模时要用到两种图:组件图和部署图。其中,使用组件图能够可视化物理组件以及它们之间的关系,并描述其构造细节。那么什么是组件图?客户服务系统的组件图是怎样的?,8.7 组件图,2. 解答问题组件图(Component Diagram)描述了软件的各种组件和它们之间的依赖关系。组件图中通常包含3种元素:组件(Component)、接口(Interface)和依赖关系(Dependency)。每个组件实现一些接口,并使用另一些接口。如果组件间的依赖关系与
47、接口有关,那么可以被具有同样接口的其他组件所替代。(1) 客户服务系统中的页面级组件图,如图8-19所示。,图8-19 客户服务系统中的页面级组件图,8.7 组件图,(2) 客户服务系统的代码级组件图(部分组件),如图8-20所示。,8.7 组件图,8.7 组件图,图8-20 客户服务系统中的代码级组件图,8.7 组件图,3. 分析问题所谓业务架构,实际上就是在对需求细致分析和深刻理解的基础上,抽象出若干相对独立的业务模块,形成自洽的业务组件。这些组件对内可以完成一个或一组特定的业务功能,对外则有着完善的接口,可以与其他组件共同组成更为复杂的业务功能,直至构成整个系统。,8.7 组件图,组件(
48、Component)是定义了良好接口的物理实现单元,是系统中可替换的物理部件。一般情况下,组件表示将类、接口等逻辑元素打包而形成的物理模块。它可以是软件代码(源代码、二进制代码或可执行代码)或其等价物(如脚本或命令文件)。在UML中,组件用一个左侧带有两个突出小矩形的矩形框来表示,如图8-20中的标有“Customer”的组件,其中Customer是组件名。组件之间的虚线箭头表示组件间的依赖关系。将组件通过一条实线相连的圆圈被称为接口,如图8-20中的“IBasedao”即为接口。,8.7 组件图,建模过程中,我们通过组件这一元素对分析设计过程中的类、接口等进行逻辑分类,一个组件表达软件的一组
49、功能。组件在很多方面与类相同:两者都有名称;都可以实现一组接口;都可以参与依赖关系;都可以被嵌套;都可以有实例;都可以参与交互。但是类和组件之间也存在着差别:类描述了软件设计的逻辑组织和意图,而组件则描述软件设计的物理实现,即每个组件体现了系统设计中特定类的实现。,8.7 组件图,组件图的一般建模步骤如下:(1) 确定组件。首先要分解系统,考虑有关系统的组成管理、软件的重用和物理节点的配置等因素,把关系密切的可执行程序和对象库分别归入组件,找出相应的对象类、接口等模型元素。(2) 对组件加上必要的构造型。可以使用UML的标准构造型executable、library、table、file、document,或自定义新的构造型,说明组件的性质。(3) 确定组件之间的关系。最常见的组件之间的关系是接口依赖。一个组件使用某个接口,另一个组件实现该接口。(4) 必要时把组件组织成包。组件和对象类等模型元素一样可以组织成包,如图8-21所示的客户服务系统组件包。 (5) 绘制组件图。,