软件设计模式(慕课版)
上QQ阅读APP看书,第一时间看更新

第1章 学习基础

1.1 软件工程简介

从始至今的软件工程发展进程中,软件工程与计算机科学之间的领域边界一直模糊不清,甚至很多人认为软件工程并非独立领域,而是隶属于计算机科学的子领域。笔者认为,软件工程与计算机科学的关系,正如计算机科学与数学之间的关系。然而,现在绝大部分人不会将计算机科学作为数学的子领域进行定义或归属。

软件工程的定义在业界有不同的表述。如,IEEE(Institute of Electrical and Electronics Engineers,美国电气与电子工程协会)在“系统与软件工程”的词条中定义软件工程为“系统地运用科学技术的知识、方法和经验,设计、实现、测试和文档化软件产品”;而在IEEE的软件工程术语词条中,则将软件工程定义为“运用系统的、规范的、定量的方法,开发、操作和维护软件产品”。

在国内,推荐性国家标准2006(GB/T 2006)在“信息技术与软件工程”术语词条中,将软件工程定义为“应用计算机科学理论和技术以及工程管理原则和方法,按预算和进度,实现满足用户要求的软件产品定义、开发、发布和维护的工程或进行研究的学科”。

软件工程作为正式术语使用,最早可追溯至NATO(North Atlantic Treaty Organization,北大西洋公约组织)于1968年(部分文献标注为1969年)在德国举办的软件工程会议,此次会议邀请了来自企业届、学术届等领域的计算机科学家、编程人员共同讨论软件危机的应对策略。之后,随着操作系统、个人计算机以及面向对象语言的出现,软件开发过程模型在20世纪80年代被人们提出;到了20世纪90年代早期,开源软件逐步发展,给软件工程带来了巨大影响。Java编程语言的出现使得软件开发更加关注软件架构,而UML(Unified Modeling Language,统一建模语言)则统一了面向对象软件模型表达方式。同时,随着Internet、分布式计算、移动互联网等技术的发展,软件工程则演变成更加关注软件产品的成本、友好度、程序效率等问题的学科。

总体上,软件工程关注或解决的软件产品开发问题包括生产率(Productivity)、质量(Quality)、成本(Costs)、时间(Time)。国际标准ISO/IEC TR 19759归纳的软件工程知识体系(Software Engineering Body of Knowledge,SWEBOK)涉及软件需求、软件设计、软件构建、软件测试、软件维护、软件配置管理、软件工程管理、软件工程过程、软件工程模型与方法、软件质量、软件工程经济学、计算机基础、数学基础及工程学基础等。

1.1.1 软件生命周期

软件生命周期(Software Lifecycle)指从软件计划开始直至软件销毁的整个周期,一般用软件开发周期(Software Development Life Cycle,SDLC)进行表达。软件开发周期一般包括6个阶段,分别为计划(Planning)、分析(Analysis)、设计(Design)、实现(Implementation)、测试与集成(Testing and Integration)、维护(Maintenance)。

最早被提出的软件开发周期模型为瀑布模型(Waterfall Model)。很多文献资料中一般会将瀑布模型的提出者标注为美国计算机科学家Winston W. Royce,因为,其在1970年发表的IEEE论文“Managing the Development of Large Software Systems”中,首次描述了瀑布模型。但是,瀑布模型作为软件工程术语正式使用要推迟至1976年。

瀑布模型的得名因其将软件开发过程从上至下分成6个阶段,每一阶段都衔接在上一阶段之后,如图1.1所示。

图1.1 瀑布模型

图1.1中,从软件计划开始至软件维护阶段,自上而下形成了一个完整的软件开发周期。瀑布模型是一种理想软件开发周期模型。它假定软件需求是稳定不变的,要求下一阶段的软件开发活动必须在上一阶段活动完成后开始。然而,在实际的软件开发业务中,软件需求的易变特性往往会导致其他阶段活动在开展时反复实施,从而增加软件开发风险。

为了解决软件需求不明确或不稳定之类的问题,后来人提出了原型模型(Prototyping Model),如图1.2所示。

图1.2中,原型模型的软件开发阶段包括初步需求、原型设计、编码实现、原型测试、原型评估和软件交付。值得注意的是,由于软件需求不稳定,原型评估阶段需要决定是进行下一周期的原型优化,还是将软件交付给客户。如果需要进行下一周期的原型优化,软件开发人员会在原型评估的基础上继续进行原型设计、编码实现等,直到最终形成可交付的软件产品。

原型模型能够很好地解决软件需求不稳定或不明确可能造成的开发问题,但由于原型开发的成本不易控制,也会产生开发成本超支、需求分析不充分等问题。此外,在实践中,人们将原型模型分成快速原型(Rapid Prototyping)、增量原型(Incremental Prototyping)、迭代原型(Evolutionary Prototyping)和螺旋模型(Spiral Model)等。快速原型模型强调原型开发的时间短,主要是为了通过原型获取更精确的软件(用户)需求。根据快速原型模型所开发的软件原型一般都存在明显的软件缺陷,最终一般都会被丢弃。增量原型则是在每个原型周期开发出最终软件产品的一部分功能子集,最终形成完整的软件产品。迭代原型与增量原型类似,只是更加注重在原型周期中开发出较为完整的软件,在不同的原型周期开发中优化和迭代上一周期的产品。螺旋模型是在原型模型的基础上加入了风险分析与控制的活动,使得原型产品开发的风险更加可控。

图1.2 原型模型

此外,还有一些软件开发周期模型,如Rational统一过程(Rational Unified Process,RUP)模型、敏捷过程(Agile Process)模型等,读者可以做进一步针对性了解和熟悉。

软件开发周期模型指出了每个开发阶段的活动或任务,但没有明确地指出如何具体实施软件开发计划,包括实施步骤、成果规范、工具或环境、实现技术等。因此,软件技术人员或学习者通过软件开发周期模型,仅仅形成了软件开发周期的概念模型,仍然需要进一步学习更多软件开发的实践方法或技术。

1.1.2 软件开发方法

软件开发方法定义了如何实施软件开发周期模型的每个阶段任务,包括计划、构建和控制这些任务时所使用到的方法、工具及技术等。常用的软件开发方法有结构化方法、面向对象方法、敏捷方法、可视化方法等。

结构化方法于20世纪70年代被提出,分为结构化分析(Structured Analysis,SA)方法和结构化设计(Structured Design,SD)方法。结构化分析采用自顶向下(Top Down)的方法,以数据流(Data Flows)的方式构建软件逻辑视图,将软件功能定义为数据流中的处理过程。结构化设计依据低耦合(Low Coupling)、高内聚(Hign Cohesion)的原则,使用结构图(Structure Chart,SC)、数据字典(Data Dictionary)等对软件模块结构及模块接口进行设计。

图1.3所示的是COS系统部分数据流图(Data Flow Diagram,DFD)示例。数据流图一般包括系统功能(加工/处理,用圆角矩形符号标识)、外部实体(用直角矩形标识)、数据存储(用开口矩形或平行线标识)和数据流向(用带箭头直线标识)。图1.3所示的数据流图中,客户向COS (Cafeteria Ordering System,订餐系统)系统中输入订单信息,COS系统生成订单并存储,COS系统向配餐员发送配送指令。

图1.3 COS系统部分数据流图示例

(注:COS系统需求见附录A)

结构图以“自顶向下”的视角对系统进行可视化建模。图1.4表达了COS系统中“下订单”“生成订单”“确认订单”“支付订单”等模块之间的逻辑关系结构图。图1.4中,“下订单”模块调用“生成订单模块”,并将“订单”数据发送至“确认订单”模块,最后调用“支付订单”模块获取支付结果。

图1.4 COS系统订单模块部分结构图示例

使用面向结构(或过程)编程语言,如Fortran、Basic、C等,可以很好地实现结构化方法设计软件。

由于没有明确软件或程序设计的优化规范,也没有定义软件需求分析和设计文档标准;当软件系统规模或复杂度达到一定程度后,使用结构化方法进行软件开发会变得越来越困难。“面向对象”提出了一种以对象为中心的软件系统分析、设计与实现的软件开发方法,能够在应对较大规模或较高复杂度的软件系统构建问题方面起到很好的作用