第5章 软件工程基础知识&5.3 系统分析与设计&5.4软件测试
5.3 系统分析与设计
系统分析阶段是应用系统思想和方法,把复杂的对象分解为简单的组成部分,找出这些部分的基本属性和彼此之间的关系的过程,其基本任务是系统分析师和用户在充分了解用户需求的基础上,把双方对新系统的理解表达为系统需求规格说明书。
系统设计的目标是根据系统分析的结果,完成系统的构建过程。其主要目的是绘制系统的蓝图,权衡和比较各种技术和实施方法的利弊,合理分配各种资源,构建新系统的详细设计方案和相关模型,指导系统实施工作的顺利开展。系统设计的主要内容包括概要设计和详细设计。
5.3.1结构化方法
1978年, E.Yourdon和 L.L.Constantine提出了结构化方法,即 SASD(Structured Analysisand Structured Design) 方法,也可称为面向功能的软件开发方法或面向数据流的软件开发方法。Yourdon方法是20世纪80年代使用最广泛的软件开发方法。
结构化开发方法提出了一组提高软件结构合理性的准则,如分解与抽象、模块独立性、信息隐蔽等。针对软件生存周期各个不同的阶段,它有结构化分析 (SA)、 结构化设计 (SD) 和结构化编程 (SP) 等方法。
1.结构化分析
结构化分析方法给出一组帮助系统分析人员产生功能规约的原理与技术。它一般利用图形表达用户需求,使用的手段主要有数据流图、数据字典、结构化语言、判定表以及判定树等。
结构化分析的步骤如下:
(1)分析业务情况,做出反映当前物理模型的数据流图 (Data Flow Diagram,DFD);
(2)推导出等价的逻辑模型的 DFD;
(3)设计新的逻辑系统,生成数据字典和基元描述;
(4)建立人机接口,提出可供选择的目标系统物理模型的 DFD;
(5)确定各种方案的成本和风险等级,据此对各种方案进行分析;
(6)选择一种方案;
(7)建立完整的需求规约。
结构化分析的常用手段是数据流图 (DFD) 和数据字典。
1)数据流图
DFD需求建模方法,也称为过程建模和功能建模方法。DFD建模方法的核心是数据流,从应用系统的数据流着手以图形方式刻画和表示一个具体业务系统中的数据处理过程和数据流。DFD 建模方法首先抽象出具体应用的主要业务流程,然后分析其输入,如其初始的数据有哪些,这些数据从哪里来,将流向何处,又经过了什么加工,加工后又变成了什么数据,这些数据流最终将得到什么结果。通过对系统业务流程的层层追踪和分析把要解决的问题清晰地展现及描述出来,为后续的设计、编码及实现系统的各项功能打下基础。
DFD 方法由4种基本元素(模型对象)组成:数据流、处理/加工、数据存储和外部项。
(1)数据流 (Data Flow)。 数据流用一个箭头描述数据的流向,箭头上标注的内容可以是信息说明或数据项。
(2)处理 (Process)。 表示对数据进行的加工和转换,在图中用矩形框表示。指向处理的数据流为该处理的输入数据,离开处理的数据流为该处理的输出数据。
(3)数据存储。表示用数据库形式(或者文件形式)存储的数据,对其进行的存取分别以指向或离开数据存储的箭头表示。
(4)外部项。也称为数据源或者数据终点。描述系统数据的提供者或者数据的使用者,如教师、学生、采购员、某个组织或部门或其他系统,在图中用圆角框或者平行四边形框表示。
建立DFD 图的目的是描述系统的功能需求。DFD方法利用应用问题域中数据及信息的提供者与使用者、信息的流向、处理、存储4种元素描述系统需求,建立应用系统的功能模型。具体的建模过程及步骤如下。
(1)明确目标,确定系统范围。首先要明确目标系统的功能需求,并将用户对目标系统的功能需求完整、准确、一致地描述出来,然后确定模型要描述的问题域。虽然在建模过程中这些内容是逐步细化的,但必须自始自终保持一致、清晰和准确。
(2)建立顶层 DFD 图。
顶层DFD图表达和描述了将要实现的系统的主要功能,同时也确定了整个模型的内外关系,表达了系统的边界及范围,也构成了进一步分解的基础。
(3)构建第一层DFD分解图。
根据应用系统的逻辑功能,把顶层DFD 图中的处理分解成多个更细化的处理。
(4)开发 DFD层次结构图。
对第一层DFD分解图中的每个处理框作进一步分解,在分解图中要列出所有的处理及其相关信息,并要注意分解图中的处理与信息包括父图中的全部内容。分解可采用以下原则:保持均匀的模型深度;按困难程度进行选择;如果一个处理难以确切命名,可以考虑对它重新分解。
(5)检查确认DFD 图。
按照规则检查和确定 DFD 图,以确保构建的DFD模型是正确的、一致的,且满足要求。具体规则包括:父图中描述过的数据流必须要在相应的子图中出现;一个处理至少有一个输入流和一个输出流;一个存储必定有流入的数据流和流出的数据流;一个数据流至少有一端是处理端;模型图中表达和描述的信息是全面的、完整的、正确的和一致的。
经过以上过程与步骤后,顶层图被逐层细化,同时也把面向问题的术语逐渐转化为面向现实的解法,并得到最终的DFD层次结构图。层次结构图中的上一层是下一层的抽象,下一层是上一层的求精和细化,而最后一层中的每个处理都是面向一个具体的描述,即一个处理模块仅描述和解决一个问题。
2)数据字典
数据字典 (Data Dictionary) 是一种用户可以访问的记录数据库和应用程序元数据的目录。数据字典是指对数据的数据项、数据结构、数据流、数据存储、处理逻辑等进行定义和描述,其目的是对数据流程图中的各个元素做出详细的说明。简而言之,数据字典是描述数据的信息集合,是对系统中使用的所有数据元素定义的集合。
数据字典最重要的作用是作为分析阶段的工具。任何字典最重要的用途都是供人查询,在结构化分析中,数据字典的作用是给数据流图上每个元素加以定义和说明。换句话说,数据流图上所有元素的定义和解释的文字集合就是数据字典。数据字典中建立的严密一致的定义,有助于改进分析员和用户的通信与交互。数据字典各部分的描述如下。
(1)数据项:数据流图中数据块的数据结构中的数据项说明。数据项是不可再分的数据单位。对数据项的描述通常包括以下内容:数据项描述={数据项名,数据项含义说明,别名,数据类型,长度,取值范围,取值含义,与其他数据项的逻辑关系}
其中“取值范围”“与其他数据项的逻辑关系”定义了数据的完整性约束条件,是设计数据检验功能的依据。若干个数据项可以组成一个数据结构。
(2)数据结构:数据流图中数据块的数据结构说明。数据结构反映了数据之间的组合关系。一个数据结构可以由若干个数据项组成,也可以由若干个数据结构组成,或由若干个数据项和数据结构混合组成。对数据结构的描述通常包括以下内容:
数据结构描述={数据结构名,含义说明,组成:{数据项或数据结构}}
(3)数据流:数据流图中流线的说明。数据流是数据结构在系统内传输的路径。对数据流的描述通常包括以下内容:
数据流描述={数据流名,说明,数据流来源,数据流去向,组成:{数据结构},平均流量,高峰期流量}
其中“数据流来源”是说明该数据流来自哪个过程,即数据的来源。“数据流去向”是说明该数据流将到哪个过程去,即数据的去向。“平均流量”是指在单位时间(每天、每周、每月等)里的传输次数。“高峰期流量”则是指在高峰时期的数据流量。
(4)数据存储:数据流图中数据块的存储特性说明。数据存储是数据结构停留或保存的地方,也是数据流的来源和去向之一。对数据存储的描述通常包括以下内容:
数据存储描述={数据存储名,说明,编号,流入的数据流,流出的数据流,组成:{数据结构},数据量,存取方式}
其中“数据量”是指每次存取多少数据,每天(或每小时、每周等)存取几次等信息。“存取方式”包括是批处理,还是联机处理;是检索还是更新;是顺序检索还是随机检索等。另外“流入的数据流”要指出其来源,“流出的数据流”要指出其去向。
(5)处理过程:数据流图中功能块的说明。数据字典中只需要描述处理过程的说明性信息,通常包括以下内容:处理过程描述={处理过程名,说明,输入:{数据流},输出:{数据流},处理:{简要说明}}
其中“简要说明”中主要说明该处理过程的功能及处理要求。功能是指该处理过程用来做什么(并不是怎么样做);处理要求包括处理频度要求,如单位时间里处理多少事务,多少数据量,响应时间要求等,这些处理要求是后面物理设计的输入及性能评价的标准。
2.结构化设计
结构化设计 (Structured Design,SD) 是一种面向数据流的设计方法,它以SRS和 S A阶段所产生的数据流图和数据字典等文档为基础,是一个自顶向下、逐步求精和模块化的过程。S D方法的基本思想是将软件设计成由相对独立且具有单一功能的模块组成的结构,分为概要设计和详细设计两个阶段,其中概要设计的主要任务是确定软件系统的结构,对系统进行模块划分,确定每个模块的功能、接口和模块之间的调用关系;详细设计的主要任务是为每个模块设计实现的细节。
1)模块结构
系统是一个整体,它具有整体性的目标和功能,但这些目标和功能的实现又是由相互联系的各个组成部分共同工作的结果。人们在解决复杂问题时使用的一个很重要的原则,就是将它分解成多个小问题分别处理,在处理过程中,需要根据系统总体要求,协调各业务部门的关系。在S D 中,这种功能分解就是将系统划分为模块,模块是组成系统的基本单位,它的特点是可以自由组合、分解和变换,系统中任何一个处理功能都可以看成一个模块。
(1)信息隐藏与抽象。
信息隐藏原则要求采用封装技术,将程序模块的实现细节(过程或数据)隐藏起来,对于不需要这些信息的其他模块来说是不能访问的,使模块接口尽量简单。按照信息隐藏的原则,系统中的模块应设计成“黑盒”,模块外部只能使用模块接口说明中给出的信息,例如,操作和数据类型等。模块之间相对独立,既易于实现,也易于理解和维护。
抽象原则要求抽取事物最基本的特性和行为,忽略非本质的细节,采用分层次抽象的方式可以控制软件开发过程的复杂性,有利于软件的可理解性和开发过程的管理。通常,抽象层次包括过程抽象、数据抽象和控制抽象。
(2)模块化。
在 S D方法中,模块是实现功能的基本单位,它一般具有功能、逻辑和状态3个基本属性,其中功能是指该模块“做什么”,逻辑是描述模块内部“怎么做”,状态是该模块使用时的环境和条件。在描述一个模块时,必须按模块的外部特性与内部特性分别描述。模块的外部特性是指模块的模块名、参数表和给程序乃至整个系统造成的影响,而模块的内部特性则是指完成其功能的程序代码和仅供该模块内部使用的数据。对于模块的外部环境(例如,需要调用这个模块的上级模块)来说,只需要了解这个模块的外部特性就足够了,不必了解它的内部特性。而软件设计阶段,通常是先确定模块的外部特性,然后再确定它的内部特性。
(3)耦合。
耦合表示模块之间联系的程度。紧密耦合表示模块之间联系非常强,松散耦合表示模块之间联系比较弱,非直接耦合则表示模块之间无任何直接联系。模块的耦合类型通常分为7种,根据耦合度从低到高排序如表5-1所示。

对于模块之间耦合的强度,主要依赖于一个模块对另一个模块的调用、一个模块向另一个模块传递的数据量、一个模块施加到另一个模块的控制的多少,以及模块之间接口的复杂程度。
(4)内聚。
内聚表示模块内部各代码成分之间联系的紧密程度,是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做目标单一的一件事情。模块的内聚类型通常也可以分为7种,根据内聚度从高到低的排序如表5-2所示。

一般说来,系统中各模块的内聚越高,则模块间的耦合就越低,但这种关系并不是绝对的。耦合低使得模块间尽可能相对独立,各模块可以单独开发和维护;内聚高使得模块的可理解性和维护性大大增强。因此,在模块的分解中应尽量减少模块的耦合,力求增加模块的内聚,遵循“高内聚、低耦合”的设计原则。
2)系统结构图
系统结构图 (Structure Chart,SC) 又称为模块结构图,它是软件概要设计阶段的工具,反映系统的功能实现和模块之间的联系与通信,包括各模块之间的层次结构,即反映了系统的总体结构。在系统分析阶段,系统分析师可以采用 S A方法获取由DFD、 数据字典和加工说明等组成的系统的逻辑模型;在系统设计阶段,系统设计师可根据一些规则,从 DFD 中导出系统初始的SC。
详细设计的主要任务是设计每个模块的实现算法、所需的局部数据结构。详细设计的目标有两个:实现模块功能的算法要逻辑上正确和算法描述要简明易懂。详细设计必须遵循概要设计来进行。详细设计方案的更改,不得影响到概要设计方案;如果需要更改概要设计,必须经过项目经理的同意。详细设计,应该完成详细设计文档,主要是模块的详细设计方案说明。
设计的基本步骤如下。
(1)分析并确定输入/输出数据的逻辑结构。
(2)找出输入数据结构和输出数据结构中有对应关系的数据单元。
(3)按一定的规则由输入、输出的数据结构导出程序结构。
(4)列出基本操作与条件,并把它们分配到程序结构图的适当位置。
(5)用伪码写出程序。
详细设计的表示工具有图形工具、表格工具和语言工具。
(1)图形工具。
利用图形工具可以把过程的细节用图形描述出来。具体的图形有业务流图、程序流程图、
PAD(Problem Analysis Diagram) 图、N S 流程图(由Nassi和 Shneiderman开发,简称 NS) 等。
程序流程图又称为程序框图,是使用最广泛然的一种描述程序逻辑结构的工具。它用方框表示一个处理步骤,菱形表示一个逻辑条件,箭头表示控制流向。其优点是:结构清晰,易于理解,易于修改。缺点是:只能描述执行过程而不能描述有关的数据。
N S 流程图,也称为盒图,是一种强制使用结构化构造的图示工具,也称为方框图。其具有以下特点:功能域明确、不可能任意转移控制、很容易确定局部和全局数据的作用域、很容易表示嵌套关系及模板的层次关系。
PAD 图是一种改进的图形描述方式,可以用来取代程序流程图,相比程序流程图更直观,结构更清晰。最大的优点是能够反映和描述自顶向下的历史和过程。PAD提供了5种基本控制结构的图示,并允许递归使用。PAD的特点如下:
● 使用PAD符号设计出的程序代码是结构化程序代码;
● PAD所描绘的程序结构十分清晰;
● 用PAD图表现程序的逻辑易读、易懂和易记;
● 容易将PAD图转换成高级语言源程序自动完成;
● 既可以表示逻辑,也可用来描绘数据结构;
● 支持自顶向下方法的使用。
(2)表格工具。
可以用一张表来描述过程的细节,在这张表中列出了各种可能的操作和相应的条件。
(3)语言工具。
用某种高级语言来描述过程的细节,例如伪码和PDL(Program Design Language) 等。
PDL 也可称为伪码或结构化语言,它用于描述模块内部的具体算法,以便开发人员之间比较精确地进行交流。语法是开放式的,其外层语法是确定的,而内层语法则不确定。外层语法描述控制结构,它用类似于一般编程语言控制结构的关键字表示,所以是确定的。内层语法描述具体操作,考虑到不同软件系统的实际操作种类繁多,内层语法因而不确定,它可以按系统的具体情况和不同的设计层次灵活选用。
● PDL的优点:可以作为注释直接插在源程序中;可以使用普通的文本编辑工具或文字处理工具产生和管理;已经有自动处理程序存在,而且可以自动由PDL生成程序代码。
● PDL的不足:不如图形工具形象直观,描述复杂的条件组合与动作间对应关系时,不如判定树清晰简单。
3.结构化编程
结构化程序设计 (Structured Programing,SP) 思想是最早由E.W.Dijikstra在1965年提出的。“面向结构”的程序设计方法即结构化程序设计方法,是“面向过程”方法的改进,结构上将软件系统划分为若干功能模块,各模块按要求单独编程,再组合构成相应的软件系统。该方法强调程序的结构性,所以容易做到易读易懂。该方法思路清晰,做法规范,程序的出错率和维护费用大大减少。
结构化程序设计采用自顶向下、逐步求精的设计方法,各个模块通过“顺序、选择、循环”的控制结构进行连接,并且只有一个入口和一个出口。
结构化程序设计的原则可表示为:程序=(算法)+(数据结构)。
算法是一个独立的整体,数据结构(包含数据类型与数据)也是一个独立的整体。两者分开设计,以算法(函数或过程)为主。
结构化程序设计提出的原则可以归纳为32个字:自顶向下,逐步细化;清晰第一,效率第二;书写规范,缩进格式;基本结构,组合而成。
4.数据库设计
数据库设计是指根据用户的需求,在某一具体的数据库管理系统上,设计数据库的结构和建立数据库的过程。数据库设计的内容包括:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库的实施和数据库的运行和维护。本小节主要讨论数据库的概念结构设计,其他内容详见数据库章节。
1)概念结构设计
概念结构设计是对用户要求描述的现实世界(可能是一个工厂、商场、学校或企业等),通过对其中实体事物的分类、聚集和概括,建立抽象的概念数据模型。这个概念模型应反映现实世界各部门的信息结构、信息流动情况、信息间的互相制约关系以及各部门对信息储存、查询和加工的要求等。通常采用实体-联系图 (Entity Relationship Diagram,E-R图)来表示。
E-R图提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。它是描述现实世界关系概念模型的有效方法,是表示概念关系模型的一种方式。
在E-R图中有如下成分:矩形框表示实体;菱形框表示联系;椭圆形框表示实体或联系的属性,对于主属性名,则在其名称下画一条下画线。
(1)实体。一般认为,客观上可以相互区分的事物就是实体,实体可以是具体的人和物,也可以是抽象的概念与联系。关键在于一个实体能与另一个实体相区别,具有相同属性的实体具有相同的特征和性质。用实体名及其属性名集合来抽象和刻画同类实体。在 E-R图中用矩形表示,矩形框内写明实体名;比如学生张三、学生李四都是实体对象。
(2)属性。实体所具有的某一特性,一个实体可由若干个属性来刻画。属性不能脱离实体,属性是相对实体而言的。在E-R 图中用椭圆形表示,并用无向边将其与相应的实体连接起来;比如学生的姓名、学号、性别都是属性。如果是多值属性的话,在椭圆形外面再套实线椭圆。如果是派生属性则用虚线椭圆表示。
(3)联系。联系也称关系,信息世界中反映实体内部或实体之间的关联。实体内部的联系通常是指组成实体的各属性之间的联系;实体之间的联系通常是指不同实体集之间的联系。在E-R图中用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体连接起来,同时在无向边旁标上联系的类型(1:1,1: n 或 m:n)。比如老师给学生授课存在授课关系,学生选课存在选课关系。如果是弱实体的联系则在菱形外面再套菱形。
E-R 图中的联系存在3种一般性约束:一对一约束(联系)、一对多约束(联系)和多对多约束(联系),它们用来描述实体集之间的数量约束。
(1)一对一联系(1:1)。
对于两个实体集A 和 B , 若 A 中的每一个值在B 中至多有一个实体值与之对应,反之亦然,则称实体集A 和 B 具有一对一的联系。个学校只有一个正校长,而一个校长只在一个学校中任职,则学校与校长之间具有一对一联系。
(2)一对多联系(1: N)。
对于两个实体集A 和 B, 若 A 中的每一个值在 B 中有多个实体值与之对应,反之B 中每一个实体值在A 中至多有一个实体值与之对应,则称实体集A 和 B 具有一对多的联系。
例如,某校教师与课程之间存在一对多的联系“教”,即每位教师可以教多门课程,但是,每门课程只能由一位教师来教,教师与课程之间具有一对多联系。一个专业中有若干名学生,而每个学生只在一个专业中学习,专业与学生之间具有一对多联系。
(3)多对多联系 (M:N)。
对于两个实体集A 和 B, 若 A 中每一个实体值在B 中有多个实体值与之对应,反之亦然,则称实体集 A 与实体集B 具有多对多联系。实际上,一对一联系是一对多联系的特例,而一对多联系又是多对多联系的特例。例如,表示学生与课程间的联系“选修”是多对多的,即一个学生可以学多门课程,而每门课程可以有多个学生来学。联系也可能有属性。例如,学生“选修”某门课程所取得的成绩,既不是学生的属性也不是课程的属性。由于“成绩”既依赖于特定学生又依赖于某门特定的课程,所以它是学生与课程之间的联系“选修”的属性。
E-R 图的基本作图步骤如下。
(1)确定所有的实体集合。
(2)选择每个实体集应该包含的属性。
(3)确定实体集之间的联系。
(4)确定实体集的关键字,用下画线在属性上表明关键字的属性组合。
(5)确定联系的类型,在用线将表示联系的菱形框联系到实体集时,在线旁注明是1或n来表示联系的类型。
5.3.2面向对象方法
面向对象 (Object-Oriented,OO) 开发方法将面向对象的思想应用于软件开发过程中,指导开发活动,是建立在“对象”概念基础上的方法学。面向对象方法的本质是主张参照人们认识一个现实系统的方法,完成分析、设计与实现一个软件系统,提倡用人类在现实生活中常用的思维方法来认识和理解描述客观事物,强调最终建立的系统能映射问题域,使得系统中的对象,以及对象之间的关系能够如实地反映问题域中固有的事物及其关系。
面向对象开发方法认为客观世界是由对象组成的,对象由属性和操作组成,对象可按其属性进行分类,对象之间的联系通过传递消息来实现,对象具有封装性、继承性和多态性。面向对象开发方法是以用例驱动的、以体系结构为中心的、迭代的和渐增式的开发过程,主要包括需求分析、系统分析、系统设计和系统实现4个阶段,但是,各个阶段的划分不像结构化开发方法那样清晰,而是在各个阶段之间迭代进行的。
1.面向对象分析
面向对象的分析方法 (Object-Oriented Analysis,OOA), 是在一个系统的开发过程中进行了系统业务调查以后,按照面向对象的思想来分析问题。OOA与结构化分析有较大的区别。OOA 所强调的是在系统调查资料的基础上,针对O O 方法所需要的素材进行的归类分析和整理,而不是对管理业务现状和方法的分析。
OOA模型由5个层次(主题层、对象类层、结构层、属性层和服务层)和5个活动(标识对象类、标识结构、定义主题、定义属性和定义服务)组成。在这种方法中定义了两种对象类之间的结构,一种称为分类结构;另一种称为组装结构。分类结构就是所谓的一般与特殊的关系。组装结构则反映了对象之间的整体与部分的关系。
1)OOA原则
OOA的基本原则包括如下内容。
(1)抽象。抽象是从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征。抽象是形成概念的必须手段。抽象是面向对象方法中使用最为广泛的原则。抽象原则包括过程抽象和数据抽象两个方面。过程抽象是指,任何一个完成确定功能的操作序列,其使用者都可以把它看作一个单一的实体,尽管实际上它可能是由一系列更低级的操作完成的。数据抽象是根据施加于数据之上的操作来定义数据类型,并限定数据的值只能由这些操作来修改和观察。据抽象是OOA 的核心原则。它强调把数据(属性)和操作(服务)结合为一个不可分的系统单位(即对象),对象的外部只需要知道它做什么,而不必知道它如何做。
(2)封装。封装就是把对象的属性和服务结合为一个不可分的系统单位,并尽可能隐蔽对象的内部细节。这个概念也经常用于从外部隐藏程序单元的内部表示或状态。
(3)继承。特殊类的对象拥有其对应的一般类的全部属性与服务,称作特殊类对一般类的继承。在OOA中运用继承原则,在特殊类中不再重复地定义一般类中已定义的东西,但是,在语义上,特殊类却自动地、隐含地拥有一般类(以及所有更上层的一般类)中定义的全部属性和服务。继承原则的好处是:使系统模型比较简练也比较清晰。
(4)分类。分类就是把具有相同属性和服务的对象划分为一类,用类作为这些对象的抽象描述。分类原则实际上是抽象原则运用于对象描述时的一种表现形式。
(5)聚合。聚合又称组装,其原则是:把一个复杂的事物看成若干比较简单的事物的组装体,从而简化对复杂事物的描述。
(6)关联。关联是人类思考问题时经常运用的思想方法:通过一个事物联想到另外的事物。能使人发生联想的原因是事物之间确实存在着某些联系。
(7)消息通信。这一原则要求对象之间只能通过消息进行通信,而不允许在对象之外直接地存取对象内部的属性。通过消息进行通信是由于封装原则而引起的。在OOA 中要求用消息连接表示出对象之间的动态联系。
(8)粒度控制。一般来讲,人在面对一个复杂的问题域时,不可能在同一时刻既能纵观全局,又能洞察秋毫。因此需要控制自己的视野:考虑全局时,注意其大的组成部分,暂时不考虑具体的细节;考虑某部分的细节时则暂时撇开其余的部分。这就是粒度控制原则。
(9)行为分析。现实世界中事物的行为是复杂的,由大量的事物所构成的问题域中各种行为往往相互依赖、相互交织。
2)基本步骤
OOA大致上遵循如下5个基本步骤。
(1)确定对象和类。这里所说的对象是对数据及其处理方式的抽象,它反映了系统保存和处理现实世界中某些事物的信息的能力。类是多个对象的共同属性和方法集合的描述,它包括如何在一个类中建立一个新对象的描述。
(2)确定结构。结构是指问题域的复杂性和连接关系。类成员结构反映了泛化-特化关系,整体-部分结构反映整体和局部之间的关系。
(3)确定主题。主题是指事物的总体概貌和总体分析模型。
(4)确定属性。属性就是数据元素,可用来描述对象或分类结构的实例,可在图中给出,并在对象的存储中指定。
(5)确定方法。方法是在收到消息后必须进行的一些处理方法:方法要在图中定义,并在对象的存储中指定。对于每个对象和结构来说,那些用来增加、修改、删除和选择的方法本身都是隐含的(虽然它们是要在对象的存储中定义的,但并不在图上给出),而有些则是显示的。
2.面向对象设计
面向对象设计方法 (Object-Oriented Design,OOD) 是 OOA方法的延续,其基本思想包括抽象、封装和可扩展性,其中可扩展性主要通过继承和多态来实现。在OOD 中,数据结构和在数据结构上定义的操作算法封装在一个对象之中。由于现实世界中的事物都可以抽象出对象的集合,所以 OOD方法是一种更接近现实世界、更自然的系统设计方法。类封装了信息和行为,是面向对象的重要组成部分,它是具有相同属性、方法和关系的对象集合的总称。在系统中,每个类都具有一定的职责,职责是指类所担任的任务。一个类可以有多种职责,设计得好的类一般至少有一种职责。在定义类时,将类的职责分解为类的属性和方法,其中属性用于封装数据,方法用于封装行为。设计类是OOD 中最重要的组成部分,也是最复杂和最耗时的部分
在OOD 中,类可以分为3种类型:实体类、控制类和边界类。
1)实体类
实体类映射需求中的每个实体,是指实体类保存需要存储在永久存储体中的信息,例如,在线教育平台系统可以提取出学员类和课程类,它们都属于实体类。实体类通常都是永久性的,它们所具有的属性和关系是长期需要的,有时甚至在系统的整个生存期都需要。实体类对用户来说是最有意义的类,通常采用业务领域术语命名,一般来说是一个名词,在用例模型向领域模型的转化中,一个参与者一般对应于实体类。通常可以从SRS 中的那些与数据库表(需要持久存储)对应的名词着手来找寻实体类。通常情况下,实体类一定有属性,但不一定有操作。
2)控制类
控制类是用于控制用例工作的类,一般是由动宾结构的短语(“动词+名词”或“名词+动词”)转化来的名词,例如,用例“身份验证”可以对应于一个控制类“身份验证器”,它提供了与身份验证相关的所有操作。控制类用于对一个或几个用例所特有的控制行为进行建模,控制对象(控制类的实例)通常控制其他对象,因此,它们的行为具有协调性。
控制类将用例的特有行为进行封装,控制对象的行为与特定用例的实现密切相关,当系统执行用例的时候,就产生了一个控制对象,控制对象经常在其对应的用例执行完毕后消亡。通常情况下,控制类没有属性,但一定有方法。
3)边界类
边界类用于封装在用例内、外流动的信息或数据流。边界类位于系统与外界的交接处,包括所有窗体、报表、打印机和扫描仪等硬件的接口,以及与其他系统的接口。要寻找和定义边界类,可以检查用例模型,每个参与者和用例交互至少要有一个边界类,边界类使参与者能与系统交互。边界类是一种用于对系统外部环境与其内部运作之间的交互进行建模的类。常见的边界类有窗口、通信协议、打印机接口、传感器和终端等。实际上,在系统设计时,产生的报表都可以作为边界类来处理。
边界类用于系统接口与系统外部进行交互,边界对象将系统与其外部环境的变更(例如,与其他系统的接口的变更、用户需求的变更等)分隔开,使这些变更不会对系统的其他部分造成影响。通常情况下,边界类可以既有属性也有方法。
3.面向对象编程
面向对象程序设计 (Object Oriented Programming,OOP) 是一种计算机编程架构。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的3个主要目标:重用性、灵活性和扩展性。OOP= 对象+类+继承+多态+消息,其中核心概念是类和对象。
面向对象程序设计方法是尽可能模拟人类的思维方式,使得软件的开发方法与过程尽可能接近人类认识世界、解决现实问题的方法和过程,也即使得描述问题的问题空间与问题的解决方案空间在结构上尽可能一致,把客观世界中的实体抽象为问题域中的对象。
面向对象程序设计以对象为核心,该方法认为程序由一系列对象组成。类是对现实世界的抽象,包括表示静态属性的数据和对数据的操作,对象是类的实例化。对象间通过消息传递相互通信,来模拟现实世界中不同实体间的联系。在面向对象的程序设计中,对象是组成程序的基本模块。
OOP 的基本特点有封装、继承和多态。
1)封装
封装是指将一个计算机系统中的数据以及与这个数据相关的一切操作语言(即描述每一个对象的属性以及其行为的程序代码)组装到一起,一并封装在一个有机的实体中,把它们封装在一个“模块”中,也就是一个类中,为软件结构的相关部件所具有的模块性提供良好的基础。在面向对象技术的相关原理以及程序语言中,封装的最基本单位是对象,而使得软件结构的相关部件的实现“高内聚、低耦合”的“最佳状态”便是面向对象技术的封装性所需要实现的最基本的目标。对于用户来说,对象是如何对各种行为进行操作、运行、实现等细节是不需要刨根问底了解清楚的,用户只需要通过封装外的通道对计算机进行相关方面的操作即可。
2)继承
继承是面向对象技术中的另外一个重要特点,其主要指的是两种或者两种以上的类之间的联系与区别。在面向对象技术中,继承是指一个对象针对于另一个对象的某些独有的特点、能力进行复制或者延续。如果按照继承源进行划分,则可以分为单继承(一个对象仅仅从另外一个对象中继承其相应的特点)与多继承(一个对象可以同时从另外两个或者两个以上的对象中继承所需要的特点与能力,并且不会发生冲突等现象);如果从继承中包含的内容进行划分,则继承可以分为4类,分别为取代继承(一个对象在继承另一个对象的能力与特点之后将父对象进行取代)、包含继承(一个对象在将另一个对象的能力与特点进行完全的继承之后,又继承了其他对象所包含的相应内容,结果导致这个对象所具有的能力与特点大于等于父对象,实现了对于父对象的包含)、受限继承和特化继承。
3)多态
从宏观的角度来讲,多态是指在面向对象技术中,当不同的多个对象同时接收到同一个完全相同的消息之后,所表现出来的动作是各不相同的,具有多种形态;从微观的角度来讲,多态是指在一组对象的一个类中,面向对象技术可以使用相同的调用方式来对相同的函数名进行调用,即便这若干个具有相同函数名的函数所执行的动作是不同的。
4.数据持久化与数据库
在面向对象开发方法中,对象只能存在于内存中,而内存不能永久保存数据,如果要永久保存对象的状态,需要进行对象的持久化 (Persistence), 对象持久化是把内存中的对象保存到数据库或可永久保存的存储设备中。在多层软件设计和开发中,为了降低系统的耦合度,一般会引入持久层 (Persistence Layer), 即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联,持久层的设计实现了数据处理层内部的业务逻辑和数据逻辑的解耦。
目前,关系数据库仍旧是使用最为广泛的数据库,如 DB2、Oracle、SQL Server等,因此,将对象持久化到关系数据库中,需要进行对象/关系的映射 (Object/Relation Mapping,ORM)。
随着对象持久化技术的发展,诞生了越来越多的持久化框架,目前,主流的持久化技术框架包括Hibernate、iBatis和 JDO等。
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的 ORM框架, Hibernate可以自动生成SQL 语句,自动执行,使得 Java程序员可以随心所欲地使用对象编程思维来操纵数据库。
iBatis提供 Java对象到 SQL (面向参数和结果集)的映射实现,实际的数据库操作需要通过手动编写SQL实现,与Hibernate相比, iBatis 最大的特点就是小巧,上手较快。如果不需要太多复杂的功能, iBatis 是既可满足要求又足够灵活的最简单的解决方案。
JDO(Java Data Object,Java数据对象)是SUN公司制定的描述对象持久化语义的标准API, 它是Java对象持久化的新规范。JDO 提供了透明的对象存储,对开发人员来说,存储数据对象完全不需要额外的代码(例如, JDBCAPI 的使用)。这些烦琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。
另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC 只能应用于关系型数据库,而JDO更通用,提供到任何数据底层的存储功能,包括关系型数据库、普通文件、 XML 文件和对象数据库等,使得应用的可移植性更强。
5.4软件测试
软件测试是使用人工或自动的手段来运行或测定某个软件系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别。
软件测试的目的就是确保软件的质量、确认软件以正确的方式做了用户所期望的事情,所以软件测试工作主要是发现软件的错误、有效定义和实现软件成分由低层到高层的组装过程、验证软件是否满足任务书和系统定义文档所规定的技术要求、为软件质量模型的建立提供依据。软件测试不仅是要确保软件的质量,还要给开发人员提供信息,以方便其为风险评估做相应的准备,重要的是软件测试要贯穿在整个软件开发的过程中,保证整个软件开发的过程是高质量的。
5.4.1测试方法
软件测试方法的分类有很多种,以测试过程中程序执行状态为依据可分为静态测试 (StaticTesting,ST) 和动态测试 (Dynamic Testing,DT); 以具体实现算法细节和系统内部结构的相关情况为根据可分黑盒测试、白盒测试和灰盒测试3类;从程序执行的方式来分类,可分为人工测试 (Manual Testing,MT) 和自动化测试 (Automatic Testing,AT)。
(1)静态测试。静态测试是被测程序不运行,只依靠分析或检查源程序的语句、结构、过等来检查程序是否有错误。即通过对软件的需求规格说明书、设计说明书以及源程序做结构分析和流程图分析,从而来找出错误。例如不匹配的参数,未定义的变量等。
(2)动态测试。动态测试与静态测试相对应,是通过运行被测试程序,对得到的运行结果与预期的结果进行比较分析,同时分析运行效率和健壮性能等。这种方法可简单分为3个步骤:构造测试实例、执行程序以及分析结果。
(3)黑盒测试。黑盒测试将被测程序看成是一个黑盒,工作人员在不考虑任何程序内部结构和特性的条件下,根据需求规格说明书设计测试实例,并检查程序的功能是否能够按照规范说明准确无误的运行。其主要是对软件界面和软件功能进行测试。对于黑盒测试行为必须加以量化才能够有效的保证软件的质量。
(4)白盒测试。白盒测试主要是借助程序内部的逻辑和相关信息,通过检测内部动作是否按照设计规格说明书的设定进行,检查每一条通路能否正常工作。白盒测试是从程序结构方面出发对测试用例进行设计。主要用于检查各个逻辑结构是否合理,对应的模块独立路径是否正常以及内部结构是否有效。常用的白盒测试法有控制流分析、数据流分析、路径分析、程序变异等。根据测试用例的覆盖程度,分为语句覆盖、判定覆盖、分支覆盖和路径覆盖等。
(5)灰盒测试。灰盒测试介于黑盒与白盒测试之间。灰盒测试除了重视输出相对于输入的正确性,也看重其内部的程序逻辑。但是,它不可能像白盒测试那样详细和完整。它只是简单地靠一些象征性的现象或标志来判断其内部的运行情况,因此在内部结果出现错误,但输出结果正确的情况下可以采取灰盒测试方法。因为在此情况下灰盒比白盒高效,比黑盒适用性广的优势就凸显出来了。
(6)自动化测试。自动化测试就是软件测试的自动化,即在预先设定的条件下自动运行被测程序,并分析运行结果。总的来说,这种测试方法就是将以人驱动的测试行为转化为机器执行的一种过程。
5.4.2测试阶段
从阶段上划分,软件测试可以分为单元测试、集成测试和系统测试,系统测试中又包含了多种不同的测试种类,例如功能测试、性能测试、验收测试、压力测试等。
1.单元测试
主要是对该软件的模块进行测试,通过测试以发现该模块的功能不符合/不满足期望的情况和编码错误。由于模块的规模不大,功能单一,结构较简单,且测试人员可通过阅读源程序清楚知道其逻辑结构,首先应通过静态测试方法,比如静态分析、代码审查等,对该模块的源程序进行分析,按照模块的程序设计的控制流程图,以满足软件覆盖率要求的逻辑测试要求。另外,也可采用黑盒测试方法提出一组基本的测试用例,再用白盒测试方法进行验证。若用黑盒测试方法所产生的测试用例满足不了软件的覆盖要求,可采用白盒法增补出新的测试用例,以满足所需的覆盖标准。其所需的覆盖标准应视模块的实际具体情况而定。对一些质量要求和可靠性要求较高的模块,一般要满足所需条件的组合覆盖或者路径覆盖标准。
2.集成测试
集成测试通常要对已经严格按照程序设计要求和标准组装起来的模块同时进行测试,明确该程序结构组装的正确性,发现和接口有关的问题。在这一阶段,一般采用白盒测试和黑盒测试结合的方法进行测试,验证这一阶段设计的合理性以及需求功能的实现性。
3.系统测试
一般情况下,系统测试采用黑盒测试,以此来检查该系统是否符合软件需求。本阶段的主要测试内容包括功能测试、性能测试、健壮性测试、安装或反安装测试、用户界面测试、压力测试、可靠性及安全性测试等。为了有效保证这一阶段测试的客观性,必须由独立的测试小组来进行相关的系统测试。另外,系统测试过程较为复杂,由于在系统测试阶段不断变更需求造成功能的删除或增加,从而使程序不断出现相应的更改,而程序在更改后可能会出现新的问题,或者原本没有问题的功能由于更改导致出现问题。所以,测试人员必须进行多轮回归测试。系统测试的结束标志是测试工作已满足测试目标所规定的需求覆盖率,并且测试所发现的缺陷都已全部归零。
4.性能测试
性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。负载测试和压力测试都属于性能测试,两者可以结合进行。通过负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。压力测试是通过确定一个系统的瓶颈或者不能接受的性能点,来获得系统能提供的最大服务级别的测试。
5.验收测试
验收测试是最后一个阶段的测试,是软件产品投入正式交付前的测试工作。和系统测试相比,验收测试是要满足用户需求或者与用户签订的合同(包括技术协议、技术协调单以及各个阶段用户参与的评审意见等)的各项要求,此外系统测试是软件开发过程中一项工作,而验收测试是由用户对要交付软件开展的一种测试工作。验收测试的主要目标是为用户展示所开发出来的软件符合预定的要求和有关标准,并验证软件实际工作的有效性和可靠性,确保用户能用该软件顺利完成既定的任务和功能。
通过了验收测试,该产品就可进行发布。但是,在实际交付给用户之后,开发人员是无法预测该软件用户在实际运用过程中是如何使用该程序的,所以从用户的角度出发,测试人员还应进行Alpha测试或Beta测试。Alpha 测试是在软件开发环境下由用户进行的测试,或者模拟实际操作环境进而进行的测试。Alpha 测试主要是对软件产品的功能、局域化、界面、可使用性以及性能等等方面进行评价。而Beta测试是在实际环境中由多个用户对其进行测试,并将在测试过程中发现的错误有效反馈给软件开发者。
6.其他测试
除了上述各种常规的测试种类之外,近年来由于Web应用和 App 应用的大规模兴起,也出现了一些新型的测试种类,例如 A B 测试、 Web测试中的链接测试、表单测试等。
(1)AB测试是为Web或 App界面或流程制作两个 (A/B) 或多个 (A/B/n) 版本,在同一时间维度,分别让组成成分相同(相似)的访客群组(目标人群)随机的访问这些版本,收集各群组的用户体验数据和业务数据,最后分析、评估出最好版本,正式采用。
(2)Web测试是软件测试的一部分,是针对Web 应用的一类测试。由于 Web应用与用户直接相关,又通常需要承受长时间的大量操作,因此Web 项目的功能和性能都必须经过可靠的验证。通过测试可以尽可能地多发现浏览器端和服务器端程序中的错误并及时加以修正,以保证应用的质量。由于Web具有分布、异构、并发和平台无关的特性,因而它的测试要比普通程序复杂得多,包含的测试种类也非常多。
(3)链接测试。链接是Web应用系统的一个主要特征,它是在页面之间切换和指导用户去一些未知地址页面的主要手段。链接测试可分为3个方面。首先,测试所有链接是否按指示的那样确实链接到了该链接的页面;其次,测试所链接的页面是否存在;最后,保证 Web应用系统上没有孤立的页面。
(4)表单测试。当用户通过表单提交信息的时候,都希望表单能正常工作。如果使用表单来进行在线注册,要确保提交按钮能正常工作,当注册完成后应返回注册成功的消息。如果使用表单收集配送信息,应确保程序能够正确处理这些数据,最后能让用户收到信息。要测试这些程序,需要验证服务器是否能正确保存这些数据,而且后台运行的程序能否正确解释和使用这些信息。当用户使用表单进行用户注册、登录、信息提交等操作时,必须测试提交操作的完整性,从而校验提交给服务器的信息的正确性。如果使用默认值,还要检验默认值的正确性。如果表单只能接受指定的某些值,则也要进行测试
浙公网安备 33010602011771号