第 1 章 软件工程概述 本章主要讲述软件和软件工程的概念,软件工程的产生和发展历程,以及软件过程、软件过程模型、软件开发方法等软件工程的基本理论知识和概念。本章知识图谱如图1.1所示。 图1.1 软件工程概述知识图谱 1.1 软件和软件工程的概念 1.1.1 软件的概念和特点 国际标准中对软件的定义为:与计算机系统操作有关的计算机程序、规程、规则,以及可能有的文件、文档及数据。 Boehm指出:软件是程序,以及开发、使用和维护程序所需的所有文档。它是由应用程序、系统程序、面向用户的文档及面向开发者的文档四部分构成的。 一般认为,“软件就是程序,开发软件就是编写程序”,这是一个错误观点,这种错误观点的长期存在也影响了软件工程的正常发展。 软件的特点如下: (1)软件是一种逻辑实体,不是具体的物理实体。 (2)软件产品的生产主要是研制过程。 (3)软件具有“复杂性”,其开发和运行常受到计算机系统的限制。 (4)软件成本昂贵,其开发方式目前尚未完全摆脱手工生产方式。 (5)软件虽然不存在磨损和老化问题,但存在退化问题。 图1.2所示为硬件失效率的U形曲线(浴盆曲线),说明硬件随着使用时间的增加,失效率急剧上升。 图1.2 硬件失效率的U形曲线 图1.3所示为软件失效率曲线,它没有U形曲线的右半翼,表明软件随着使用时间的增加,失效率降低;虽然软件不存在磨损和老化问题,但存在退化问题。 图1.3 软件失效率曲线 1.1.2 软件工程的定义 软件工程(software engineering)是在克服20世纪60年代末国际上出现的“软件危机”的过程中逐渐形成与发展的。自在1968年北大西洋公约组织(North Atlantic Treaty Organization,NATO)所举行的软件可靠性学术会议上为克服软件危机,正式提出“软件工程”的概念(借鉴工程化的方法来开发软件)以来,软件工程一直以来都缺乏统一的定义,很多学者、组织机构都分别给出了自己认可的定义。 例如,1983年,IEEE(国际电气与电子工程师协会)所下的定义是:软件工程是开发、运行、维护和修复软件的系统方法。1990年,IEEE又将定义更改为:将系统的、规范的、可度量的方法应用于软件的开发、运行和维护,即将工程应用于软件,并研究以上实现的途径。 ISO 9000对软件工程过程的定义是:软件工程过程是输入转换为输出的一组彼此相关的资源和活动。 Boehm则将软件工程定义为:运用现代科学技术知识来设计并构造计算机程序及为开发、运行和维护这些程序所必需的相关文件资料。 对于软件工程的各种各样的定义,它们的基本思想都是强调在软件开发过程中应用工程化原则的重要性。 从软件工程的定义可见,软件工程是一门指导计算机软件开发和维护的工程学科,它以计算机理论及其他相关学科的理论为指导,采用工程化的概念、原理、技术和方法进行软件的开发和维护,把经实践证明的科学的管理措施与最先进的技术方法结合起来。即软件工程研究的目标是“以较少的投资获取高质量的软件”。 软件工程涉及计算机科学、管理学、数学等多个学科,其研究范围广,不仅包括软件系统的开发方法和技术、管理技术,还包括软件工具、环境及软件开发的规范。 软件是信息化的核心。国民经济、国防建设、社会发展及人民生活都离不开软件。软件产业关系到国家经济发展和文化安全,体现了一个国家的综合实力,是决定21世纪国际竞争地位的战略性产业。尤其是随着互联网技术的迅速发展,软件工程对促进信息产业发展和信息化建设的作用凸显。 因此,大力推广应用软件工程的开发技术及管理技术,提高软件工程的应用水平,对促进我国软件产业与国际接轨,推动软件产业的迅速发展起着十分重要的作用。 1.2 软件工程的产生和发展 1.2.1 软件危机与软件工程 1.软件危机 20世纪60年代末期,随着软件的规模越来越大,复杂度不断提高,软件需求量也不断增大,而当时生产作坊式的软件开发模式及技术已不能满足软件发展的需要。 软件开发过程是一种高密集度的脑力劳动,需要投入大量的人力、物力和财力;由于软件开发的模式及技术不能适应软件发展的需要,大量质量低劣的软件产品涌向市场,有的甚至在开发过程中就夭折了。国外在开发一些大型软件系统时,遇到了许多困难,有的系统最终彻底失败了;有的系统则比原计划推迟了好多年,而费用大大超过了预算;有的系统功能不符合用户的需求,也无法进行修改维护。典型的例子如下: IBM公司的OS/360,共约100万条指令,花费了5000个人年,经费达数亿美元,而结果却令人沮丧,错误多达2000个及以上,系统根本无法正常运行。OS/360系统的负责人Brooks这样描述开发过程的困难和混乱:“像巨兽在泥潭中做垂死挣扎,挣扎得越猛,泥浆就沾得越多,最后没有一个野兽能够摆脱淹没在泥潭中的命运……” 1967年,苏联“联盟一号”载人宇宙飞船返航时打不开降落伞(由于其软件忽略了一个小数点的错误),当进入大气层时因摩擦力太大而被烧毁,造成机毁人亡的巨大损失。 还有,可以称为20世纪世界上最精心设计,并花费了巨额投资的美国阿波罗登月飞行计划的软件,也仍然没有避免出错。例如,阿波罗8号太空飞船由于计算机软件的一个错误,丢失了存储器的一部分信息;阿波罗14号在飞行的10天中,出现了18个软件错误。 2.软件危机的表现 软件危机,反映在软件可靠性没有保障、软件维护工作量大、费用不断上升、进度无法预测、成本增长无法控制、程序人员无限度地增加等各方面,以至于形成人们难以控制软件开发的局面。 软件危机主要表现在三方面: (1)软件生产效率低,不能满足需要。 (2)软件设计的进度无法控制。 (3)开发费用经常超出预算。 3.软件工程的概念形成 软件危机所造成的严重后果已使世界各国的软件产业危机四伏,面临崩溃,克服软件危机刻不容缓。 自软件可靠性学术会议举行以来,世界各国的软件工作者为克服软件危机进行了许多开创性的工作,在软件工程的理论研究和工程实践两方面都取得了长足进步,缓解了软件危机。但距离实现彻底克服软件危机这个软件工程的最终目标,任重道远,还需要软件工作者付出长期且艰苦的努力。 从“软件工程”的概念提出至今,软件工程的发展已经历了四个重要阶段: (1)第一代软件工程阶段。20世纪60年代末出现的“软件危机”,其表现为软件生产效率低,大量质量低劣的软件涌入市场,甚至在软件开发过程中夭折,使软件产业濒临瘫痪。 为克服“软件危机”,在软件可靠性学术会议上第一次提出了“软件工程”这一术语,这标志着将软件开发纳入了工程化的轨道,基本形成了软件工程的概念、框架、技术和方法。这一阶段又称为传统的软件工程阶段。 (2)第二代软件工程阶段。20世纪80年代中期,以Smalltalk为代表的面向对象的程序设计语言相继推出,面向对象的方法与技术得到发展;从20世纪90年代起,研究的重点从程序设计语言逐渐转移到面向对象的分析与设计,进而演化为一种完整的软件开发方法和系统的技术体系。20世纪90年代以来,出现了许多面向对象的开发方法的流派,面向对象的方法逐渐成为软件开发的主流方法。所以这一阶段又称为对象工程阶段。 (3)第三代软件工程阶段。随着软件规模和复杂度的不断增大,开发人员也随之增多,开发周期也相应延长,加之软件是知识密集型的逻辑思维产品,这些都增加了软件工程管理的难度。从20世纪80年代中期开始,人们在软件开发的实践过程中认识到:提高软件生产效率并保证软件质量的关键是对“软件过程”的控制和管理能力,即对软件开发和维护的管理和支持能力。这一阶段,对软件项目管理的计划、组织、成本估算、质量保证、软件配置管理等技术与策略相继提出,并逐步形成了软件过程工程。 (4)第四代软件工程阶段。20世纪90年代至今,基于组件的开发方法取得重要进展,软件系统的开发可通过使用现存的可重用组件组装完成,而无须从头开始构造,以此达到提高效率和质量、降低成本的目的。软件重用技术及组件技术的发展,为克服软件危机提供了一条有效途径,这一阶段称为组件工程阶段。 1.2.2 软件工程的基本原则 软件工程的基本原则是随着软件工程的发展而变化的。过去软件工程的基本原则是抽象、模块化、清晰的结构、精确的设计规格说明。但今天软件工程的基本原则已经发生了很大的变化,具体如下: (1)必须认识软件需求的变动性,以便采取适当措施来保证产品能最好地满足用户要求。在软件设计中,通常要考虑模块化、抽象与信息隐蔽、局部化、一致性等原则。 (2)稳妥的设计方法将大大方便软件开发,以实现软件工程的目标。软件工具与环境对软件设计的支持来说,颇为重要。 (3)软件工程项目的质量与经济开销取决于对它所提出的支撑质量与效用。 (4)只有在强调对软件过程进行有效管理的情况下,才能实现有效的软件工程。 1.2.3 软件工程研究的内容 软件工程涉及的学科多,研究的范围广。归结起来软件工程研究的主要内容有以下几方面。 (1)软件开发方法,主要讨论软件开发的各种方法及其工作模型,它包括多方面的任务,如软件系统需求分析、总体设计,以及构建良好的软件结构、数据结构及算法设计等,同时也包括具体实现的技术。 (2)软件工具可为软件工程方法提供支持,应研究计算机辅助软件工程(computer aided software engineering,CASE),建立软件工程环境。 (3)软件工程管理,是指对软件工程全过程的控制和管理,包括计划安排、成本估算、项目管理、软件质量管理等。 (4)软件工程标准化与规范化,使得各项工作有章可循,以保证软件生产效率和软件质量的提高。软件工程标准可分为4个层次:国际标准、行业标准、企业规范和项目规范。 此外,按照美国电子与电气工程师协会计算机学会(Institute of Electrical and Electronics Engineers-Computer Society,IEEE-CS)于2015年发布的软件工程知识体系定义的软件工程学科的内涵,软件工程研究的内容由17个知识域构成。 (1)软件需求。软件需求涉及需求抽取、需求分析、建立需求规格说明和确认等活动,还涉及建模、经济与时间可行性分析。 (2)软件设计。设计是软件工程最核心的内容。其主要活动有软件概要设计、软件详细设计,涉及软件体系结构、组件、接口,以及系统或组件的其他特征,还涉及软件设计质量分析和评估、软件设计的符号、软件设计策略和方法等。 (3)软件构造。软件构造指通过编码、单元测试、集成测试、调试、确认等活动,生成可用的、符合设计功能的软件,并要求控制和降低程序复杂性。 (4)软件测试。测试是软件生存周期的重要部分,涉及测试的标准、测试技术、测试度量和测试过程。 (5)软件维护。软件产品交付后,需要改正软件的缺陷,提高软件性能,使软件产品适应新的环境。软件维护是软件进化的继续。基于服务的软件维护越来越受到重视。 (6)软件配置管理。为了系统地控制配置变更,维护整个系统生存周期中配置的一致性和可追踪性,必须按时间管理软件的不同配置,包括配置管理过程的管理、软件配置鉴别、配置管理控制、配置管理状态记录、配置管理审计、软件发布和交付管理等。 (7)软件工程管理。软件工程管理指运用管理活动,如计划、协调、度量、监控、控制和报告,确保软件开发和维护是系统的、规范的、可度量的。它涉及基础设施管理、项目管理、度量和控制计划三个层次。 (8)软件工程模型与方法。软件工程模型与方法所涉及的内容广泛,既关注软件生存周期的特定阶段,也涵盖整个软件生存周期。 (9)软件工程过程。软件工程过程关注软件过程的定义、实现、评估、测量、管理、变更、改进,以及过程和产品的度量。 (10)软件质量。软件质量被定义为“软件产品满足明确的和在特定条件下隐含需求的能力”,或被定义为“软件产品满足约定需求的程度”。 (11)软件工程经济学。软件工程经济学主要研究软件和软件工程经济效果。它以软件或软件载体作为研究对象,以追求投入产出效益为目标,通过测算项目全生存周期的投入与产出,衡量实现软件产品、信息服务及作业预定需求之各类资源的使用效率,以提高软件工程经济效益。软件工程经济学知识领域包括软件工程经济学基础,软件生存周期的投入与产出,评估模型、方法与参数,风险与不确定性和实践考量五方面。 (12)软件服务工程。软件服务工程知识领域包括服务的体系结构设计、软件服务使用技能、服务业分析、服务管理和服务应用实践五方面。 (13)软件工程典型应用。软件工程典型应用包括网络软件及应用、企业信息系统与数据分析、电子商务与互联网金融、信息安全与安全软件、嵌入式软件与应用、多媒体与游戏软件、中文信息处理系统和典型行业相关软件八方面。 (14)软件工程职业实践。软件工程职业实践包括职业技能、团队动力与心理学、沟通技巧、企业(组织)软件开发与管理实践和软件生存周期项目开发实践五方面。 (15)计算基础。计算基础知识领域涵盖软件运行所涉及的开发与操作环境。计算基础知识领域所涉及的课程包括编程、数据结构、算法、计算机组成、操作系统、编译器、数据库、网络、分布式系统等。 (16)工程基础。IEEE对工程的定义为:应用系统的、有规律的、可度量的方法,构建结构、机器、产品、系统或过程。随着软件工程理论与实践的日益成熟,软件工程逐渐成为基于知识和技能的工程学科的重要成员。 (17)数学基础。数学基础知识能够帮助软件工程师理解程序中的逻辑流程,并将整个流程转换成能够正确运行的程序代码。数学可以理解为形式化系统。形式化必须是精确的,也就是说,对于一个事实,数学不能有任何模棱两可或者错误的解释。数学是对物理对象的普遍规律的抽象。这些物理对象可以是数字、符号、图像、声音、视频等。 必须要强调的是,随着人们对软件系统研究的逐渐深入,软件工程所研究的内容也在不断更新和发展。 1.3 软件过程 软件工程是在软件生产中采用工程化的方法,并采用一系列科学的、现代化的方法和技术来开发软件的。这种工程化的思想贯穿软件开发和维护的全过程。 为了进一步学习有关软件工程的方法和技术,首先介绍软件生存周期及软件工程过程等重要概念。 1.3.1 软件生存周期 软件生存周期,又称软件生命周期,是指一个从用户需求开始,经过开发、交付使用,在使用中不断地增补修订,直至软件报废的全过程。 软件生存周期分为以下阶段: (1)可行性研究和项目开发计划。该阶段必须要回答的问题是“软件系统要解决的问题是什么”。 (2)需求分析。该阶段的主要任务是,通过分析准确地确定“软件系统必须做什么”,即软件系统必须具备哪些功能。 (3)概要设计。概要设计也称总体设计。该阶段的主要任务是确定软件体系结构、划分子系统模块及确定模块之间的关系,并确定系统的数据结构和进行界面设计。 (4)详细设计。该阶段的主要任务是对每个模块完成的功能、算法进行具体描述,并把功能描述变为精确的、结构化的过程描述。 (5)软件构造。该阶段的主要任务是把每个模块的控制结构转换成计算机可接受的程序代码,即编写以某特定程序设计语言表示的“源代码”。 (6)测试。测试是保证软件质量的重要手段,其主要方式是在设计测试用例的基础上检验软件的各个组成部分。测试分为模块测试、组装测试、确认测试等。 (7)维护。软件维护是软件生存周期中时间最长的阶段。已交付的软件投入正式使用后,便进入软件维护阶段,它可以持续几年甚至几十年。 特别要指出的是:实际的软件开发过程,是一个充满迭代和反复的过程,上述阶段(1)到(6),通常会相互重叠,反复进行,才可能完成软件的开发。 1.3.2 软件工程过程及产品 软件工程过程是指在软件工具的支持下,所进行的一系列软件工程活动。通常包括以下4类基本过程: (1)软件规格说明。规定软件的功能及其运行环境。 (2)软件开发。产生满足规格说明的软件。 (3)软件确认。确认软件能够完成客户提出的要求。 (4)软件演进。为满足客户的变更要求,软件必须在使用的过程中演进。 软件工程过程具有可理解性、可见性(过程的进展和结果可见)、可靠性、可支持性(易于使用CASE工具支持)、可维护性、可接受性(为软件工程师接受)、开发效率和健壮性(抵御外部意外错误的能力)等特性。 软件工程有方法、工具和过程三个要素。软件工程方法研究软件开发“如何做”;软件工程工具是研究支撑软件开发方法的工具,为方法的运用提供自动或者半自动的支撑环境。软件工程工具的集成环境,又称为计算机辅助软件工程;软件工程过程则是指将软件工程方法与软件工程工具相结合,达到合理、及时地进行软件开发的目的,为开发高质量软件规定各项任务的工作步骤。如图1.4所示,在软件工程的三要素中,软件工程过程将人员、方法与规范、工具和管理有机结合,形成一个能有效控制软件开发质量的运行机制。 图1.4 软件工程过程 1.4 软件过程模型 软件过程模型也称为软件生存周期模型或软件开发模型,是描述软件过程中各种活动如何执行的模型。它确立了软件开发和演绎中各阶段的次序限制以及各阶段活动的准则,并确立了开发过程所遵守的规定和限制,便于各种活动的协调以及各种人员的有效通信,有利于活动重用和活动管理。为了描述软件生存周期的活动,人们提出了多种生存周期模型,如瀑布模型、增量模型、螺旋模型、喷泉模型、原型模型、智能模型等。 1.4.1 瀑布模型 瀑布模型是经典的软件开发模型,是1970年由Royce提出的最早的软件开发模型。如图1.5所示,瀑布模型将软件开发活动中的各个活动规定为依线性顺序连接的若干阶段,形如瀑布流水,最终得到软件系统或软件产品。换句话说,它将软件开发过程划分成若干互相区别而又彼此联系的阶段,每个阶段中的工作都以上一阶段工作的结果为依据,同时作为下一阶段的工作基础。每个阶段的任务完成之后,产生相应的文档。该模型适合需求很明确的软件项目开发。 图1.5 瀑布模型 在软件工程的第一阶段,瀑布模型得到了广泛的应用。它简单易用,在消除非结构化软件,降低软件的复杂性,促进软件开发工程化方面起了很大的作用,但在软件开发实践中也逐渐暴露出缺点。由于瀑布模型是一种理想的线性开发模式,它将一个充满回溯的软件开发过程硬性分割为几个阶段,无法解决软件需求不明确或者变动的问题。这些缺点给软件开发带来了严重影响,例如,需求不明确会导致开发的软件不符合用户的需求而夭折。 1.4.2 增量模型 增量模型是一种非整体开发的模型。根据增量的方式和形式的不同,增量模型分为基于瀑布模型的渐增模型和基于原型模型的快速原型模型。一般的增量模型如图1.6所示。该模型具有较大的灵活性,适合软件需求不明确、设计方案有一定风险的软件项目。 图1.6 增量模型 增量模型和瀑布模型之间的本质区别是:瀑布模型属于整体开发模型,它规定在开始下一阶段的工作之前,必须完成前一阶段的所有细节;增量模型属于非整体开发模型,它推迟某些阶段或所有阶段中的细节,从而较早地产生工作软件。 1.4.3 螺旋模型 对于大型软件,只开发一个原型往往达不到要求。螺旋模型将瀑布模型和增量模型结合起来,并加入了风险分析。它是由TRW公司的Boehm于1988年提出的。该模型将开发过程划分为制订计划、风险分析、实施工程和客户评估4类活动。螺旋模型如图1.7所示,沿着螺旋线每转一圈,表示开发出一个更完善的新的软件版本。如果开发风险过大,开发机构和客户无法接受,项目有可能就此中止;多数情况下,会沿着螺旋线继续下去,自内向外逐步延伸,最终得到满意的软件产品。 螺旋模型将开发过程分为几个螺旋周期,每个螺旋周期可分为4个工作步骤: (1)制订计划:这个阶段的主要工作是确定开发目标、提出相关可供选择的方案和限制条件。 (2)风险分析:这个阶段根据前一阶段所提出的相关备选方案进行评估、标识各种方案的风险和应对风险的可行措施。 (3)实施工程:在实施工程阶段,通过不同迭代周期的工作,逐步完成软件产品的开发与验证工作,并进行产品确认。 (4)客户评估:作为每个周期的最后一个工作步骤,本阶段主要达成其前序3个阶段的里程碑,并进行相关评估,为下一阶段工作提供依据和计划。 图1.7 螺旋模型 1.4.4 喷泉模型 喷泉模型是由B.H.Sollers和J.M.Edwards于1990年提出的一种新的开发模型,主要用于采用对象技术的软件开发项目。它克服了瀑布模型不支持软件重用和多项开发活动集成的局限性。喷泉模型使开发过程具有迭代性和无间隙性。软件的某个部分常常被重复工作多次,相关对象在每次迭代中随之加入渐进的软件成分,即迭代的特性;而分析和设计活动等各个活动之间没有明显的边界,即无间隙的特性。 喷泉模型以面向对象的开发方法为基础,以用户需求作为喷泉模型的源泉。如图1.8所示,喷泉模型有如下特点: (1)喷泉模型规定软件开发过程有4个阶段,即分析、系统设计、软件设计和实现。 (2)喷泉模型的各阶段相互重叠,反映了软件过程并行性的特点。 (3)喷泉模型以分析为基础,资源消耗成塔形,在分析阶段消耗的资源最多。 (4)喷泉模型反映了软件过程迭代性的自然特性,从高层返回低层无资源消耗。 (5)喷泉模型强调增量开发,依据“分析一点,设计一点”的原则,并不要求一个阶段的彻底完成,整个过程是一个迭代的逐步提炼的过程。 (6)喷泉模型是对象驱动的过程,对象是所有活动作用的实体,也是项目管理的基本内容。 (7)喷泉模型在实现时,由于活动不同,可分为系统实现和对象实现,这既反映了全系统的开发过程,也反映了对象族的开发和重用过程。 1.4.5 原型模型 原型是软件开发过程中,软件的一个早期可运行的版本,它反映了软件系统的部分重要特性。原型模型反映了快速建立软件原型的过程。如图1.9所示,它是一个循环的模型,通常分为以下4步。 (1)快速分析。快速确定软件系统的基本要求,并确定原型所要体现的主要特征(界面、总体结构、功能、性能)。 (2)构造原型。在快速分析的基础上,根据系统的基本规格说明,忽略细节,只考虑主要特征,快速构造一个可运行的系统。 (3)运行和评价原型。用户试用原型并与开发者之间频繁交流,发现问题,目的是验证原型的正确性。 (4)修改与改进。根据所发现的问题,对原型进行修改、增删和完善。 这4步按箭头顺序反复执行,直到用户对生成的原型评价满意为止。 1.4.6 智能模型 智能模型也称为基于知识的软件开发模型,是知识工程与软件工程在开发模型上结合的产物,是以瀑布模型与专家系统的综合应用为基础建立的模型。该模型通过应用系统的知识和规则帮助设计者认识一个特定的软件的需求与设计,这些专家系统已成为开发过程的伙伴,并指导开发过程。 从图1.10中可以清楚地看到,智能模型与其他模型不同,它的维护并不在程序一级上进行,这样就把问题的复杂性大大降低了。 智能模型的主要优点如下: (1)通过领域的专家系统,可使需求说明更加完整、准确和无二义性。 (2)通过软件工程的专家系统,提供一个设计库支持,在开发过程中成为设计者的助手。 (3)通过软件工程知识和特定应用领域的知识与规则的应用来提供开发的帮助。 图1.10 智能模型 但是,要建立适合软件设计的专家系统,或建立一个既适合软件工程又适合应用领域的知识库都是非常困难的。目前,在软件开发中正在应用AI技术,并已取得了局部进展;例如在CASE工具系统中使用专家系统,又如使用专家系统实现测试自动化。 1.5 软件开发方法 为了克服软件危机,从20世纪60年代末开始,各国的软件工作者一直在进行软件开发方法的研究与实践,并取得了一系列研究成果,对软件产业的发展起着不可估量的作用。 软件工程的内容包括技术和管理两方面,且二者紧密结合。通常把在软件生存周期中所使用的一整套技术的集合称为方法学或范型。 软件开发方法是一种使用早已定义好的技术集及符号表示习惯来组织软件生产过程的方法。该方法一般表述成一系列的步骤,每一个步骤都与相应的技术和符号相关。其目标是要在规定的投资和时间内,开发出符合用户需求的、高质量的软件,为此需要成功的开发方法。 软件开发方法可分为两大类:面向过程的开发方法和面向对象的开发方法。本节将对结构化开发方法、原型化开发方法、面向对象的开发方法及敏捷开发方法进行介绍。 1.5.1 结构化开发方法 结构化开发方法是一种面向数据流的开发方法,它的指导思想是“自顶向下、逐步求精”。它的基本原则是功能的分解与抽象。该方法提出了一组提高软件结构合理性的准则,如分解和抽象、模块的独立性、信息隐蔽等。它是现有的软件开发方法中最成熟、应用最广泛的方法。该方法的主要特点是快速、自然和方便。 结构化开发方法由三部分构成,按照推出的先后次序有:20世纪70年代初期推出的结构化程序设计方法—SP(structured programming)方法;20世纪70年代中期推出的结构化设计方法—SD(structured design)方法;20世纪70年代末期推出的结构化分析方法—SA(structured analysis)方法。SA方法、SD方法、SP方法相互衔接,形成了一整套开发方法。若将SA方法和SD方法结合起来,又称为结构化分析与设计技术(structured analysis and design technique,SADT)。 结构化开发方法的工作模型—瀑布模型,从20世纪80年代开始,逐渐被发现其不足:软件开发过程是个充满回溯的过程,而瀑布模型却将其硬性分割为独立的几个阶段,不能从本质上反映软件开发过程本身的规律。此外,过分强调复审,并不能完全避免较为频繁的变动。尽管如此,瀑布模型仍然是早期开发软件产品的一个行之有效的工程模型。 1.5.2 原型化开发方法 原型反映了最终系统的部分重要特性。原型化开发方法的基本思想是,花费少量代价建立一个可运行的系统,使用户及早获得学习的机会。原型化开发方法又称快速原型法,强调的是软件开发人员与用户的不断交互,通过原型的演进不断适应用户任务改变的需求,将维护和修改阶段的工作尽早进行,用户可提前验收,从而使软件产品更加适用。原型化开发方法又分为两类: 1.快速建立需求规格原型(RSP方法) RSP(rapid specification prototyping)方法所建立的原型反映了系统的主要特征,所建立的原型是需求说明书,以让用户及早进行学习,不断对需求进行改进和完善,获得更加精确的需求说明书;需求说明书一旦确定原型即被废弃,后续的工作仍按照瀑布模型开发,所以也称为废弃型。 2.快速建立渐进原型(RCP方法) RCP(rapid cyclic prototyping)方法采用循环渐进的开发方式,对系统模型做连续精化,将系统需要具备的性质逐步添加上去,直至所有性质全部满足。此时的原型模型也就是最终的产品,所以也称为追加型。 原型化开发方法适合开发探索型、实验型与进化型一类的软件系统。原型化开发方法的工作流程如图1.11所示,它是一个多次循环的过程。 实际的软件开发通常不可能一次成功,而是一个充满反复和迭代的过程。原型化开发方法的思想符合实际的软件开发过程。 通常有三类原型:用户界面原型、功能原型和性能原型。 1.5.3 面向对象的开发方法 面向对象的开发方法是20世纪80年代推出的一种全新的软件开发方法,非常实用且强有力,被誉为20世纪90年代软件的核心技术之一。 其基本思想是:对问题领域进行自然的分割,以更接近人类通常思维的方式建立问题领域的模型,以便对客观的信息实体进行结构和行为的模拟,从而使设计的软件更直接地表现问题的求解过程。 Coad和Yourdon给出一个面向对象的定义: 面向对象=对象+类+继承+消息 如果一个软件系统是按照这四个概念来设计和实现的,则可以认为这个软件系统是面向对象的。一个面向对象的软件的每一个组成部分都是对象,计算是通过对象和对象之间的通信来执行的。 1.5.3.1 面向对象的基本概念 面向对象的开发方法以对象作为最基本的元素,是分析和解决问题的核心。对象与类是讨论面向对象方法的最基本、最重要的概念。 1.对象 对象是对客观事物或概念的抽象表述,对象不仅能表示具体的实体,也能表示抽象的规则、计划或事件。通常有以下一些对象类型。 (1)有形的实体。在现实世界中的实体都是对象,如飞机、车辆、机器、桌子、房子等。 (2)作用。作用指人或组织,如教师、学生、医生、政府机关、公司、部门等所起的作用。 (3)事件。事件指在某个特定时间内所发生的事,如学习、演出、开会、办公、事故等。 (4)性能说明。如对产品的性能指标的说明。例如,计算机主板的速度、型号、性能说明等。 每个对象都存在一定的状态、内部标识。可以给对象定义一组操作,对象通过其运算所展示的特定行为称为对象行为;对象本身的性质称为属性;对象将它自身的属性及运算“包装起来”,称为封装。因此,对象是一个封装数据属性和操作行为的实体。数据描述了对象的状态,操作可操纵私有数据,改变对象的状态。当其他对象向该对象发出消息,该对象响应时,其操作才得以实现。在对象内的操作通常称为方法。 2.类 类又称对象类,是一组具有相同数据结构和相同操作的对象的集合。类是对象的模板。在一个类中,每个对象都是类的实例,它们都可以使用类中提供的函数。例如,小轿车是一个类,红旗牌小轿车、东风牌小轿车都是它的一个对象。类具有属性,用数据结构来描述类的属性:类具有操作,它是对象行为的抽象,用操作名和实现该操作的方法,即操作实现的过程来描述。 由于对象是类的实例,在进行系统分析和设计时,通常把注意力集中在类上,而不是具体的对象上。 3.继承 继承以现存的定义作为基础,建立新定义的技术,是父类和子类之间共享数据结构和方法的机制。如图1.12所示,继承性通常表示父类与子类的关系。子类的公共属性和操作归属于父类,并为每个子类共享,子类继承了父类的特性。 图1.12 继承性 单重继承:一个子类只有一个父类,即子类只继承一个父类的数据结构和方法 继承性 多重继承:一个子类可有多个父类,继承多个父类的数据结构和方法 通过继承关系还可以构成层次关系。单重继承构成的类之间的层次关系是一棵树,多重继承构成的类之间的关系是一个网格(如果将所有无子类的类,都看成还有一个公共子类的话)。继承关系是可传递的。 4.消息 消息是指对象之间在交互中所传送的通信信息。一个消息应该包含以下信息:消息名、接收消息对象的标识、服务标识、消息和方法、输入信息、回答信息等。消息使对象之间互相联系,协同工作,实现系统的各种服务。 通常一个对象向另一个对象发送信息请求某项服务,接收对象响应该消息,激发所要求的服务操作,并将操作结果返回给请求服务的对象,这种通信机制称为消息传递。发送消息的对象不需要知道接收消息的对象如何对请求予以响应。 1.5.3.2 面向对象开发的组成 OOSD由OOA(object oriented analysis,面向对象的分析)、OOD(object oriented design,面向对象的设计)和OOP(object oriented programming,面向对象的程序设计)三部分组成。下面介绍OOA法和OOD法。 1. OOA法 OOA就是要解决“做什么”的问题。它的基本任务就是要建立以下三种模型。 (1)对象模型(信息模型):定义构成系统的类和对象,以及它们的属性与操作。 (2)状态模型(动态模型):描述任何时刻对象的联系及其联系的改变,即时序。常用状态图、事件追踪图描述。 (3)处理模型(函数模型):描述系统内部数据的传送处理。 显然,在以上三种模型中,最重要的是对象模型。 2. OOD法 在需求分析的基础上,进一步解决“如何做”的问题。OOD法也分为概要设计和详细设计。 其中面向对象的分析(OOA)与面向对象的设计(OOD)是面向对象开发方法的关键。 由于面向对象的方法以对象为核心,强调模拟现实世界中的概念而不是算法,尽量用符合人类认识世界的思维方式来渐进地分析、解决问题,对软件开发过程所有阶段进行综合考虑,能有效地降低软件开发的复杂度,使软件的易重用性和易扩充性都得到了提高,而且能更好地适应需求的变化,提高软件质量。 1.5.4 敏捷开发方法 1.5.4.1 敏捷软件开发的基本概念 敏捷软件开发又称敏捷开发,以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。20世纪90年代,软件危机得到一定程度的缓解,但随着软件项目规模和复杂度的增加,需求常常发生变化,时有软件不能如期交付的情况发生。为了按时交付软件,开发人员只好经常加班加点赶进度,而大量的文档资料也加重了他们的负担。 激烈的市场竞争也要求推出快速、高质量开发软件的方法,因此敏捷软件开发方法便应运而生。2001年2月,部分软件工作者在美国犹他州成立了“敏捷软件开发(Agile software development)联盟”,简称Agile联盟,发表了敏捷软件开发宣言,表述了与会者对软件开发的核心价值观。 (1)人和交互胜过过程和工具。 (2)可运行的软件胜过面面俱到的文档。 (3)与客户协作胜过合同谈判。 (4)对变更及时处理胜过遵循计划。 可以看出,敏捷软件开发更强调与客户的协作、人与人之间的交互与团队的协作,更重视不断向用户提交可运行的软件,而不把过多的精力放在编写详尽的文档上。尤其强调对软件需求变化的快速应变能力。基于这些价值观,敏捷软件开发必须遵守的12条原则如下。 (1)最重要的是要尽早和不断提交有价值的软件以满足客户需求。 (2)欢迎需求的变化,即使是在开发的后期,敏捷过程也能利用变化为客户提升竞争优势。 (3)经常提交可运行的软件,时间间隔(几周或几个月)越短越好。 (4)在整个项目过程中,业务人员和开发人员必须每天在一起工作。 (5)围绕有工作激情的人建立项目组,给予他们所需的环境和支持,并对他们能够完成任务予以充分信任。 (6)项目组内最有效、效率最高的信息传递方式是面对面的交流。 (7)可运行的软件是度量项目进度的首要标准。 (8)敏捷过程提倡可持续开发,项目责任人、开发者和用户应保持长期稳定的开发速度。 (9)不断追求优秀的技术和优良的设计,有助于提高敏捷性。 (10)简单化是有效降低工作量的艺术。 (11)最好的架构、需求和设计源于自我组织的团队。 (12)团队要定期进行反省,讨论如何能够更有效地工作,并对工作进行相应调整。 1.5.4.2 XP方法简介 按照敏捷软件开发的思想和原则,人们推出了许多具体的实践方法,如XP、Scrum、Crystal、Methods、FDD等。 其中XP方法是最具代表性的敏捷开发方法,又称极限编程。它是由Kent Beck于1999年提出来的。极限编程以用户需求作为软件开发的最终目标,是一种以实践为基础的软件工程过程。极限编程强调测试,是一种测试驱动的开发方法,强调代码质量和及早发现问题,以适应环境和需求的变化。 1.核心价值观 XP方法的核心价值观为:沟通、简单、反馈和勇气。 (1)沟通。沟通是项目成功的关键,只有开发人员与用户、开发人员之间频繁而有效地面对面交流信息,充分理解用户需求,才能够保证软件开发的质量和效率。 (2)简单。为了保证高效开发,在满足用户需求的前提下,软件开发全过程及过程中的产品都应该尽量简单。 (3)反馈。及时、准确的信息反馈,能够使开发人员及时发现开发工作中的问题和偏差并及时纠正。 (4)勇气。采用敏捷开发这种新的开发方法,就是一种挑战,是需要勇气的;在开发过程中需要团队密切协作,既要相信别人也要相信自己一定能够完成,这需要勇气。另外,只有十分需要的文档才写,即使写也要简单明了,这也需要勇气。 2. XP方法的最佳实践 在其核心价值观的指导下,XP方法提出以下12项最佳实践。 (1)规划策略。通过结合使用业务优先级和技术评估来快速制订计划,确定下一个版本的范围。 (2)小型发布。将一个简单系统迅速投入生产,以很短的周期发布新版本,供用户评估使用。 (3)系统隐喻。用合适的比喻传达信息,通过隐喻来描述系统如何运作、新的功能以何种方式加入系统,通常包含了一些可以参照和比较的类与设计模式。 (4)简单设计。任何时候都应当将系统设计为尽可能简单。不必要的复杂性一旦被发现就马上去掉。 (5)测试。程序员不断地进行单元测试,在这些测试能够准确无误地运行的情况下,开发才可以继续。客户编写测试来证明系统各功能都已经完成。 (6)重构。程序员重新构造系统以去除重复、改善沟通、简化或提高系统柔性。 (7)结对编程。所有的生产代码都是由两个程序员在同一台机器上编写的,这样能够随时交流,及时发现和解决问题。 (8)代码集体所有。任何人在任何时候都可以在系统中的任何位置更改任何代码。 (9)持续集成。每天多次集成和生成系统,每次都完成一项任务。 (10)每周工作40 h。一般情况下,一周工作不超过40 h。不要连续两个星期都加班。 (11)现场客户。在团队中加入一位真正的、起作用的用户,他将全职负责回答问题。 (12)编码标准。程序员依照强调通过代码沟通的规则来编写所有代码。 这12项最佳实践,就是强调开发者之间、开发者与用户之间的充分交流、密切协作,快速、高效地不断测试、集成和推出系统。 3. XP方法的开发过程 XP方法以面向对象的方法作为推荐的开发范型。XP方法包含了策划、设计、编码和测试4个框架活动的规则和实践。图1.13描述了XP方法的开发过程,并指出与各框架活动相关的关键概念和任务。特别要说明,XP方法的开发过程的主要特点:它是一个不断迭代的过程。 图1.13 XP方法的开发过程 4.敏捷开发的原则 (1)快速迭代。在敏捷开发中,软件项目在构建初期被分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。也就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。 相对于那种半年一次的大版本发布来说,小版本的需求、开发和测试更加简单快速。 (2)让测试人员和开发者参与需求讨论。需求讨论以小组的形式展开最有效率,且必须要包括测试人员和开发者,这样可以更加轻松地定义可测试的需求,将需求分组并确定优先级。同时,该种方式也可以充分利用团队成员间的互补特性。如此确定的需求往往比开需求讨论大会的形式效率更高,大家更活跃,参与感更强。 (3)编写可测试的需求文档。开始就要用“用户故事”的方法来编写需求文档。这种方法可以让我们将注意力放在需求上,而不是解决方法和实施技术上。过早地提及技术实施方案,会降低对需求的注意力。 (4)多沟通,尽量减少文档。任何项目中,沟通都是一个常见的问题。好的沟通,是敏捷开发的先决条件。工作时间越久,人们越会强调高效沟通的重要性。团队要确保日常的交流,面对面沟通比邮件沟通效率高得多。 (5)做好产品原型。建议使用草图和模型来阐明用户界面,因为并不是所有人都可以理解一份复杂的文档,但人人都会看图。 (6)及早考虑测试。及早考虑测试在敏捷开发中很重要。传统的软件开发,测试用例很晚才开始写,这导致过晚发现需求中存在的问题,使得改进成本过高。较早地开始编写测试用例,当需求完成时,可以接受的测试用例也基本一块完成了。 章节习题 1.软件产品的特点是什么?(关联知识点1.1.1节) 2.软件工程发展有几个阶段?各有何特征?(关联知识点1.2.1节) 3.什么是软件危机?其产生的原因是什么?(关联知识点1.2.1节) 4.什么是软件过程?有哪些主要的软件过程模型?它们各有哪些特点?(关联知识点1.3节、1.4节) 5.有哪些主要的软件开发方法?(关联知识点1.5节) 6.软件生存周期各阶段的主要任务是什么?(关联知识点1.3.1节) 7.原型化开发方法的核心是什么?它具有哪些特点?(关联知识点1.5.2节) 8.面向对象的开发方法为什么逐渐成为软件开发的主流方法?(关联知识点1.5.3节) 9.什么是软件开发环境?它对软件开发过程有何意义?(关联知识点1.1节、1.4节) 10.敏捷软件开发的核心思想是什么?以XP方法为例进行说明。(关联知识点1.5.4节)