开发模型
瀑布模型
瀑布模型产生的历史背景是20世界70年代出现的软件危机,该模型将软件开发分为若干阶段,由于其类似于瀑布从上到下的过程,故称其为“瀑布模型”。
- 特点:
- 阶段间具有顺序性和依赖性:
- 前一阶段完成后,才能开始后一阶段
- 前一阶段的输出文本为后一阶段的输入文本
? - 推迟实现的观点
? - 质量保证: - 每个阶段必须交付出合格的文档
? - 对文档进行审核
- 缺点:
开始需要把需求做到最全,惧怕用户测试中的反馈,惧怕需求变更。
V模型
V模型是在瀑布模型的基础上发展而来的。
RAD(Rap Application Development,快速应用开发)模型是软件开发过程中的一个重
要模型,由于其模型构图形似字母V,所以又称软件测试的 V模型。它通过开发和测试同时进行的方式来缩短开发周期,提高开发效率。
阶段步骤
V模型大体可以划分为以下几个不同的阶段步骤:需求分析、概要设计、详细设计、软件编码、单元测试、集成测试、系统测试、验收测试。
- 需求分析:
首先要明确客户需要的是什么,需要软件作成什么样子,需要有哪几项功能,这一点上比较关键的是分析师和客户沟通时的理解能力与交互性。要求分析师能准确地把客户所需要达到的功能、实现方式等表述出来,给出分析结果,写出需求规格说明书。 - 概要设计:
主要是架构的实现,指搭建架构、表述各模块功能、模块接口连接和数据传递的实现等多项事务。 - 详细设计:
对概要设计中表述的各模块进行深入分析、对各模块组合进行分析等,这一阶段要求达到伪代码级别,已经把程序的具体实现的功能、现象等表述出来。其中需要包含数据库设计说明。 - 软件编码:
按照详细设计好的模块功能表,编程人员编写出实际的代码。 - 单元测试:
按照设定好的最小测试单元进行按单元测试,主要是测试程序代码,为的是确保各单元模块被正确的编译。
单元的具体划分,依据不同的单位、不同的软件而有所不同,比如有具体到模块的测试,也有具体到类、函数的测试等。 - 集成测试:
经过了单元测试后,将各单元组合成完整的体系,主要测试各模块间组合后的功能实现情况,以及模块接口连接的成功与否,数据传递的正确性等。
其主要目的是检查软件单位之间的接口是否正确。
根据集成测试计划,一边将模块或其他软件单位组合成系统,一边运行该系统,以分析所组成的系统是否正确,各组成部分是否合拍。 - 系统测试:
经过了单元测试和集成测试以后,我们要把软件系统搭建起来,按照软件规格说明书中所要求,测试软件其性能、功能等是否和用户需求相符合,在系统中运行是否存在漏洞,等。 - 验收测试:
主要就是用户在拿到软件的时候,在使用现场,会根据前边所提到的需求,以及规格说明书来做相应测试,以确定软件达到符合效果的。
缺陷及解决思路
缺陷:
V模型仅仅把测试过程作为在需求分析、系统设计及编码之后的一个阶段,忽视了测试对需求分析,系统设计的验证,需求的满足情况一直到后期的验收测试才被验证。
解决思路:
当一个软件开发的时候,研发人员和测试人员需要同时工作,测试在软件做需求分析的同时就会有测试用例的跟踪,这样,可以尽快找出程序错误和需求偏离,从而更高效的提高程序质量,最大可能的减少成本,同时满足用户的实际软件需求。
适用范围
V模式是一种传统软件开发模型,一般适用于一些传统信息系统应用的开发;而一些高性能高风险的系统、互联网软件,或一个系统难以被具体模块化的时候,就比较难做成V模式所需的各种构件,需要更强调迭代的开发模型或者敏捷开发模型。
W模型
W模型:由Evolutif公司提出,相对于V模型,W模型增加了软件开发各阶段中同步进行的验证和确认活动。
如图所示,由两个V字型模型组成,分别代表测试与开发过程,图中明确表示出了测试与开发的并行关系。
- 优点:
- 开发伴随着整个开发周期,需求和设计同样要测试;
- 更早的介入测试,可以发现初期的缺陷,修复成本低; - 分阶段工作,方便项目整体管理。
- 缺点:
- 开发和测试依然是线性的关系,需求的变更和调整,依然不方便;
- 如果没有文档,根本无法执行w模型;对于项目组成员的技术要求更高!
软件生命周期
瀑布型生命周期
瀑布型生命周期包括可行性分析与开发项计划、需求分析、设计(概要设计和详细设计)、编码、测试、维护等阶段。
阶段步骤
- 问题的定义及规划:
此阶段是软件开发方与需求方共同讨论,主要确定软件的开发目标及其可行性。 - 需求分析:
在确定软件开发可行的情况下,对软件需要实现的各个功能进行详细分析。需求分析阶段是一个很重要的阶段,这一阶段做得好,将为整个软件开发项目的成功打下良好的基础。"唯一不变的是变化本身。",同样需求也是在整个软件开发过程中不断变化和深入的,因此我们必须制定需求变更计划来应付这种变化,以保护整个项目的顺利进行。 - 软件设计:
此阶段主要根据需求分析的结果,对整个软件系统进行设计,如系统框架设计,数据库设计等等。软件设计一般分为总体设计和详细设计。好的软件设计将为软件程序编写打下良好的基础。 - 程序编码:
此阶段是将软件设计的结果转换成计算机可运行的程序代码。在程序编码中必须要制定统一,符合标准的编写规范。以保证程序的可读性,易维护性,提高程序的运行效率。 - 软件测试:
在软件设计完成后要经过严密的测试,以发现软件在整个设计过程中存在的问题并加以纠正。整个测试过程分单元测试、组装测试以及系统测试三个阶段进行。测试的方法主要有白盒测试和黑盒测试两种。在测试过程中需要建立详细的测试计划并严格按照测试计划进行测试,以减少测试的随意性。 - 运行维护:
软件维护是软件生命周期中持续时间最长的阶段。在软件开发完成并投入使用后,由于多方面的原因,软件不能继续适应用户的要求。要延续软件的使用寿命,就必须对软件进行维护。软件的维护包括纠错性维护和改进性维护两个方面。
高内聚低耦合
- 内聚:是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系;
- 耦合:是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。
- 耦合性:也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。
内聚性:又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。
- 所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则。
对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。
耦合
耦合可以分为以下几种,它们之间的耦合度由高到低排列如下:
- 内容耦合:一个模块直接访问另一模块的内容,则称这两个模块为内容耦合。
内容耦合可能在汇编语言中出现。大多数高级语言都已设计成不允许出现内容耦合。
这种耦合的耦合性最强,模块独立性最弱。 - 公共耦合:一组模块都访问同一个全局数据结构,则称之为公共耦合。
公共数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
如果模块只是向公共数据环境输入数据,或是只从公共数据环境取出数据,这属于比较松散的公共耦合;
如果模块既向公共数据环境输入数据又从公共数据环境取出数据,这属于较紧密的公共耦合。 - 外部耦合:一组模块都访问同一全局简单变量,而且不通过参数表传递该全局变量的信息,则称之为外部耦合。
- 控制耦合:模块之间传递的不是数据信息,而是控制信息例如标志、开关量等,一个模块控制了另一个模块的功能。
- 标记耦合:调用模块和被调用模块之间传递数据结构,而不是简单数据,同时也称作特征耦合。
标记耦合的模块间传递的不是简单变量,而是像高级语言中的数据名、记录名和文件名等数据结果,这些名字即为标记,其实传递的是地址。 - 数据耦合:调用模块和被调用模块之间只传递简单的数据项参数。相当于高级语言中的值传递。
- 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。
耦合度最弱,模块独立性最强。
总结:耦合是影响软件复杂程度和设计质量的一个重要因素,为提高模块的独立性,应建立模块间尽可能松散的系统,在设计上我们应采用以下原则:若模块间必须存在耦合,应尽量使用数据耦合,少用控制耦合,慎用或有控制地使用公共耦合,并限制公共耦合的范围,尽量避免内容耦合。
内聚
内聚有如下的种类,它们之间的内聚度由弱到强排列如下:
- 偶然内聚:一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一起。
这种模块也称为巧合内聚,内聚程度最低。 - 逻辑内聚:这种模块把几种相关的功能组合在一起,每次被调用时,由传送给模块参数来确定该模块应完成哪一种功能。
- 时间内聚:把需要同时执行的动作组合在一起,形成的模块称为时间内聚模块。
- 过程内聚:构件或者操作的组合方式是,允许在调用前面的构件或操作之后,马上调用后面的构件或操作,即 使两者之间没有数据进行传递。
简单的说就是如果一个模块内的处理元素是相关的,而且必须以特定次序执行,则称为过程内聚。 - 通信内聚(信息内聚):指模块内所有处理元素都在同一个数据结构上操作或所有处理功能都通过公用数据而发生关联(有时称之为信息内聚)。
即 指模块内各个组成部分都使用相同的数据数据或产生相同的数据结构。 - 顺序内聚:一个模块中各个处理元素和同一个功能密切相关,而且这些处理必须顺序执行,通常前一个处理元素的输出是后一个处理元素的输入。
例如,某模块完成工业产值求值的功能,前一个功能元素求总产值,后一个功能元素求平均产值,显然该模块内两部分紧密关联。
顺序内聚的内聚度比较高,但缺点是不如功能内聚易于维护。 - 功能内聚:模块内所有元素的各个组成部分全部都为完成同一个功能而存在,共同完成一个单一的功能,模块已不可再分。即 模块仅包括为完成某个功能所必须的所有成分,这些成分紧密联系、缺一不可。
功能内聚是最强的内聚,其优点是它的功能明确。判断一个模块是否功能内聚,一般从模块名称就能看出。
如果模块名称只有一个动词和一个特定的目标(单数名词),一般来说就是功能内聚,如:“计算水费”、“计算产值”等模块。功能内聚一般出现在软件结构图的较低层次上。
功能内聚模块的一个重要特点是:他是一个“暗盒”,对于该模块的调用者来说,只需要知道这个模块能做什么,而不需要知道这个模块是如何做的。
总结:在模块划分时,要遵循“一个模块,一个功能”的原则,尽可能使模块达到功能内聚。
高内聚,低耦合的系统有什么好处呢?
事实上,短期来看,并没有很明显的好处,甚至短期内会影响系统的开发进度,因为高内聚,低耦合的系统对开发设计人员提出了更高的要求。
高内聚,低耦合的好处体现在系统持续发展的过程中,高内聚,低耦合的系统具有更好的重用性,维护性,扩展性,可以更高效的完成系统的维护开发,持续的支持业务的发展,而不会成为业务发展的障碍。