软件工程导论《软件工程实用案例教程》

0
(0)

第一章 软件工程综述

  • 什么是软件?软件有什么特点?
  • 什么是软件危机?为什么会出现软件危机?
  • 什么是软件工程?为什么它很重要?
  • 软件工程的目标是什么?软件工程三要素是什么?
  • 什么是软件工程的多样性?软件工程通用原则有哪些?
  • 了解道德和职业问题对于软件工程的重要性。

软件工程的背景

软件及其特性

  1. 计算机软件:是与计算机系统操作有关的程序、规程、规则及其文档和数据的统称。
    • 组成:(1) 计算机可执行的程序和有关的数据 (2) 软件开发、运行、维护、使用和培训有关的文档
      • 程序:按事先设计的功能和性能要求执行的语句序列
      • 数据:程序所处理信息的数据结构
      • 文档:与程序开发、维护和使用相关的各种图文资料
  2. 软件产品主要有以下两类:(1) 通用软件产品 (2) 定制软件产品
    • (1) 由软件开发机构制作,在市场上公开销售,可以独立使用
    • (2) 受特定的客户委托,由软件承包商专门为某类客户开发
    • 区别:软件描述由开发人员完成和由客户给出
  3. 软件的固有特性
    • 复杂性:软件是一个庞大的逻辑系统
    • 抽象性:软件是人们经过大脑思维后加工出来的产品(工作量难以估计、进度难以控制、质量难以把握)
    • 依赖性:软件的开发和运行往往受硬件的限制,两者对计算机系统有不同程度的依赖性(可移植性问题)
    • 软件使用特性:软件的价值在于应用,软件产品不会因多次反复使用而磨损老化;软件投入运行后,总会存在缺陷甚至暴露出潜伏的错误,需要进行长期的维护及再开发
  4. 软件生产特性
    • 软件开发特性:技术复杂性(功能多、功能实现具有多样性、实现算法上优化带来的不同、实现差异导致使用差别)、管理复杂性(能见度低: 难以把握开发进度、结构合理性差: 结构不合理使管理复杂性随软件规模增大而呈指数增长)
    • 软件产品形式的特性:设计成本高昂、生产成本极低。(人力物力资金投入和质量控制产品检验都在开发中进行,开发成功后复制非常容易,软件的知识产权保护极为重要)
    • 软件维护特性:纠错性维护(修正缺陷和错误)、完善性维护(改善性能修改功能)、适应性维护(适配软硬件环境改变)。软件产品规模庞大、内部逻辑关系复杂时,经常发生纠正一个错误而产生新的错误的情况,软件维护工作量大且复杂。

软件危机

20世纪60-70年代,由于软件规模扩大、功能增强和复杂性增加,在一定时间内依靠少数人开发一个软件越来越困难。软件开发中经常出现时间延迟、预算超支、质量得不到保证、移植性差等问题,甚至有的项目耗费大量人力财力后,由于离目标相差甚远而宣布失败。

  1. 软件危机的突出表现
    • 软件生产率低:落后的生产方式与开发人员匮乏,难以积累和复用开发知识、经验、数据,低水平重复开发
    • 软件产品常常与用户要求不一致:开发人员与用户之间缺少合适的交流方法和需求描述工具,获取的需求常常存在二义性、遗漏、错误
    • 软件规模增长带来复杂度增加:缺乏有效的软件开发方法和工具的支持,过分依赖开发人员,导致软件可靠性随着软件规模增长而下降,质量保证困难
    • 不可维护性突出:局限性和欠灵活性,难以适配新环境,也很难增加新功能
    • 软件文档不完全、不一致:软件文档是计算机软件的重要组成部分。开发过程中,管理人员需要使用文档资料来管理软件项目;技术人员需要利用文档资料进行信息交流;用户也需要通过文档认识软件,对软件验收
  2. 产生软件危机的原因
    • 软件独有的特点给开发和维护带来困难:软件的抽象性、复杂性与不可预见性,使得软件在运行之前难以衡量开发过程的进展,软件错误发现晚,质量难评价。软件错误还具有隐蔽性,往往在很长时间里软件仍可能需要改错
    • 软件人员的错误认识:对软件开发和维护的错误观念,忽视软件需求分析的重要性,轻视文档的作用,轻视软件维护等
    • 软件开发工具自动化程度低:软件生产工程化管理程度低,无法避免低水平的重复性劳动,浪费财力物力和宝贵的人力资源

软件工程概述

软件工程的基本概念

  • 按工程化的原则和方法组织软件开发工作是有效的,是摆脱软件危机的一个主要出路。
  • 「为了经济地获得可靠的、能在实际机器上高效运行的软件,而建立和使用的健全的工程原则」
  • 软件工程是:① 将系统化的、规范化的、可量化的方法应用于软件的开发、运行和维护中,即将工程化方法应用于软件;② 对于①中所述方法的研究。
  • 软件工程是指导计算机软件开发和维护的工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它。
  • 我们需要规范,也需要可适应性和灵活性。

软件工程的目标

  • 软件开发成本较低
  • 软件功能能够满足用户的需求
  • 软件性能较好
  • 软件可靠性高
  • 软件易于使用、维护和移植
  • 能够按时完成开发任务,并及时交付使用

实际开发中,有些目标是相互补充的,有些目标是彼此相互冲突的,不同的应用对软件质量的要求不同,如对实时系统来说,其可靠性和效率比较重要,对生命周期较长的软件来说,其可移植性和可维护性比较重要。

软件工程三要素

将软件的质量作为根基,软件工程研究的内容包括过程、方法、工具这三个方面,也被称为「软件工程三要素」。

  1. 软件质量可用功能性、可靠性、可用性、效率、可维护性和可移植性等特性来评价。
    • 功能性是指软件所实现的功能能达到它的设计规范和满足用户需求的程度
    • 可靠性是指在规定的时间和条件下,软件能够正常维持其工作的能力
    • 可用性是指为了使用该软件所需要的能力
    • 效率是指在规定的条件下用软件实现某种功能所需要的计算机资源的有效性
    • 可维护性是指当环境变化和软件运行发生故障时,为了使其恢复正常运行所做的努力的程度
    • 可移植性是指软件从某一环境转移到另一个环境时所有努力的程度
  2. 软件工程的基础是过程(Process):一个通用的软件工程过程框架通常包含以下6个活动
    • 沟通:了解利益相关者的项目目标,收集需求及定义软件特性和功能
    • 策划:软件项目计划定义和描述了软件工程工作,包括需要执行的技术任务、可能的风险、资源需求、工作产品和工作进度计划
    • 建模:利用模型来更好地理解软件需求,并完成符合这些需求的软件设计
    • 构建:对所做的设计进行构建,包括编码和测试,后者用于发现编码中的错误
    • 部署:交付软件给用户,用户对其进行评测并给出反馈意见
    • 进化:随不同客户和变化的市场需求进行修改
  3. 软件工程框架活动由很多支持性活动补充实现。典型的支持性活动有以下几个。
    • 软件项目跟踪和控制:根据计划评估项目进度,采取必要措施保证项目按进度计划进行
    • 风险管理:对可能影响项目成果或产品质量的风险进行评估
    • 软件质量保证:确定和执行保证软件质量的活动
    • 技术评审:尽量在错误传播到下一个活动之前发现并清除
    • 测量:定义和收集过程、项目及产品的度量,帮助团队在发布软件时满足利益相关者的要求
    • 软件配置管理:在整个软件过程中管理变更所带来的影响
    • 可复用管理:定义工作产品复用的标准,建立构件复用机制
    • 工作产品的准备和生产:包括生产产品所必须的活动(建模、文档、例子、表格和列表等)
  4. 软件工程方法(Method):为构建软件提供技术上的解决方案,主要有以下两种方法
    • 传统结构化方法
      • 传统的基于软件生命周期的软件工程方法。以软件功能为目标来进行软件构建,包括结构化分析、结构化设计、结构化实现、结构化维护等内容。
      • 主要通过数据流模型来描述软件的数据加工过程,并通过数据流模型,由对软件的分析过渡到对软件的结构设计。
    • 面向对象方法
      • 从现实世界中客观存在的事物出发来构造软件,包括面向对象分析、面向对象设计、面向对象实现、面向对象维护等内容。
      • 一个软件是为了解决某些问题,这些问题所涉及的业务范围被称作该软件的问题域。面向对象强调以问题域中的事物为中心来思考问题、认识问题,并根据这些事物的本质特征,把它抽象地表示为系统中的对象,作为系统的基本构成单位。
      • 确定问题域中的对象成分及其关系,建立软件系统对象模型,是面向对象分析与设计过程中核心内容。
  5. 软件工程工具(Tool):辅助软件开发、维护和管理的软件
    • 计算机辅助软件工程(Computer Aided Software Engineering, CASE)是通过一组集成化的工具,辅助软件开发人员实现各项活动的全部自动化,使软件产品在整个生命周期中的开发和维护生产率得到提高,质量得到保证。

软件工程的多样性

没有一个通用的软件工程方法和技术适合所有的系统和公司。决定使用哪一种软件工程方法和技术主要取决于要开发的应用的类型。

  1. 系统软件:整套服务于其他程序的程序。某些系统软件(如编译器、编辑器、文件管理软件)处理复杂但确定的系统结构,另一些系统应用程序(如操作系统构建、驱动程序、网络软件、远程通信处理器)主要处理的是不确定的数据。
  2. 独立的应用软件:解决特定业务需要的独立应用程序,运行在本地,拥有所有必要的功能不需要连接网络。(办公软件、CAD、图片处理软件等)
  3. 嵌入式控制系统:由一个软件控制系统和管理硬件设备。(汽车仪表盘显示、控制防抱死的软件、微波炉控制烹饪过程的软件)
  4. 以网络为中心的交互式应用:在远程计算机上执行,用户通过自己的终端进行访问,包括基于浏览器的Web应用和安装在移动设备上的APP,以及基于云计算的广泛计算机资源的共享。
  5. 娱乐系统:主要是个人用户用于娱乐。主要是游戏,交互质量是与其他系统的一个重要区别。
  6. 建模和仿真系统:科学家和工程师用于模拟物理过程或环境,通常是计算密集型的,需要高性能并行系统才能运行。
  7. 数据采集系统:用一些传感器从环境中采集数据并发送这些数据给其它系统进行处理。软件必须能与传感器交互且通常安装在恶劣环境中。
  8. 人工智能软件:利用非数值算法解决计算和直接分析无法解决的复杂问题。(机器人、专家系统、模式识别、人工神经网络、定理证明和博弈等)

软件工程与Web

最常见的Web应用有以下三种结构。

  1. C/S(Client/Server, 客户端/服务器)结构
    • 通常将数据库安装在服务器端,应用程序安装在客户端。(如银行ATM机取款系统)
    • 数据库集中存放的目的是方便实现数据共享。应用程序需要数据库中的数据时,才通过网络访问数据库服务器,因此C/S结构的网络资源比较少。
    • 优点:系统安装在内部局域网中,安全性较高,受外界影响较小;系统及时性较好,满足快速响应需求;数据库集中存放,共享程度高。
    • 问题:应用程序升级时需要对若干台计算机同步升级操作,否则会产生版本不同步问题;集中存放的数据库可以被多个用户同时访问,存在系统内部的安全性控制问题。
  2. B/S(Browse/Server, 浏览器/服务器)结构
    • 数据库和应用程序均被安装在服务器端,客户端计算机不安装应用程序,通过浏览器来访问服务器应用程序,再由服务器应用程序访问数据库。(如新闻浏览网站、电子商务网站)
    • 需要一直占用网络资源,因此访问速度与计算机网络的带宽、访问量等技术指标有关,但可以不考虑地域的限制,可以在广域网或内部局域网运行。
    • 优点:应用程序升级时只需升级服务端应用程序,客户端通过刷新浏览器便可运行最新版本的应用程序。
    • 问题:系统可以建立在广域网上,安全性受到威胁,需要面对目前网络上的黑客攻击、病毒传播等问题,必须有良好的安全措施予以保障,如配置防火墙、安装防病毒软件等;应用程序运行过程中的人机交互是靠不断刷新浏览器页面来实现的,对系统的运行效率有较大的影响,目前通过Ajax技术,可以在无须重新加载页面的情况下对网页的某部分进行更新。
  3. 云计算
    • 云计算是使计算分布在大量的分布式计算机上,而非本地服务器或远程服务器中。
    • 「云」具有相当的规模,Google云计算已经拥有100多万台服务器,Amazon、IBM、微软、Yahoo等的「云」均拥有几十万台服务器,企业私有云一般拥有数百上千台服务器。「云」能赋予用户前所未有的计算能力,云计算支持用户在任意位置、使用各种终端获取应用服务,所请求的资源来自「云」,而不是固定的、有形的实体。
    • 目前云平台所能提供的服务有:①用户可以租用一台虚拟服务器来发布自己的网站;②可以为自己的计算机部署某种基础软件环境,如操作系统、Java开发环境;③为企业客户提供办公平台及应用;④为企业或客户提供网络安全配置服务;⑤提供各种API(Application Programming Interface, 应用程序编程接口)服务;⑥提供数据分析、数据计算、数据存储服务等。当然这些服务都是需要收费的。
    • 「云」使用了数据多副本容错、计算节点同构可互换等措施来保障服务的高可靠性,使用云计算比使用本地计算机可靠。云计算不针对特定的应用,在「云」的支撑下可以构造出千变万化的应用,同一个「云」可以同时支撑不同的应用运行。由于「云」的特殊容错措施可以采用极其廉价的节点来构成「云」,「云」的自动化集中式管理使大量企业无需负担日益高昂的数据中心管理成本,「云」的通用性使资源的利用率较之传统系统大幅提升,因此用户可以充分享受「云」的低成本优势。
    • 云计算服务除了提供计算服务外,还提供了存储服务。但云计算服务当前垄断在私人机构(企业)手中,而他们仅仅能够提供商业信用。对于政府机构、商业机构(特别像银行这样持有敏感数据的商业机构)对于选择云计算服务应保持足够的警惕。一旦商业用户大规模使用私人机构提供的云计算服务,无论其技术优势有多强,都不可避免地让这些私人机构以「数据(信息)」的重要性来挟制整个社会。对于信息社会而言,「信息」是至关重要的。云计算中的数据对于数据所有者以外的其他云计算用户是保密的,但对于提供云计算的商业机构却是毫无秘密可言。
    • 云计算的实现需要开发包含前端和后端服务的体系结构。前端包括客户设备和应用软件(如浏览器),用于访问后端。后端包括服务器和相关的计算资源、数据存储系统(如数据库)、服务器驻留应用程序和管理服务器。通过建立对「云」及其驻留资源的一系列访问协议管理服务器,使用中间件对流量进行协调和监控。

软件工程的通用原则

  1. 第一原则:存在价值
    • 一个文件系统应能为用户提供价值而具有存在价值,所有的决策都应该基于这个思想。所有的其他原则都以这条原则为基础。
  2. 第二原则:有管理的软件过程
    • 软件开发机构应规划它们的开发过程,并清楚地知道产出什么及什么时候完工。
  3. 第三原则:可用性和信息安全性
    • 软件应该如所期待的那样表现,没有失败且在用户需要时是可用的。它也应该是操作安全且信息安全的,能抵御来自外部的攻击。同时系统应是高效的,不会浪费资源。
  4. 第四原则:需求工程
    • 理解和管理系统需求及描述,你必须知道不同的客户和用户的期望是什么,然后管理这些期望以便在预算范围内按期交付一个有用的系统。需求说明时时刻想到用户,设计中始终想到实现,编码时想着要维护和扩展系统的人,尽可能地使他们的工作简单化会大大提升系统的价值。
  5. 第五原则:提前计划复用
    • 尽可能高效地使用当前存在的资源。应该在适当的地方复用已开发的软件,而不是重新写一个。
    • 为达到面向对象程序设计技术所能提供的复用性,需要有前瞻性的设计和计划。提前做好复用计划将降低开发费用,并增加可复用构件及构件化系统的价值。
  6. 第六原则:面向未来
    • 生命周期持久的系统具有更高的价值。真正具有「产业实力」的软件系统必须持久耐用。系统必须能适应各种变化,因此一开始就应以这种路线来设计系统。

软件工程人员的职业道德

用软件工程人员职业生涯中经常会面临的简单抉择举例如下。

  • 场景一:你觉得一个软件项目有问题,你会选择什么时机向管理层报告呢?如果只是在怀疑,这时向管理层报告未免有点敏感;如果时间拖得过长,则有可能延误了解决难题的时机。
  • 场景二:当你的意见和团队内部的观点甚至是高层领导的决策发生冲突时,是据理力争,还是坚持原则毅然辞职,或是妥协,哪种方法是最好的呢?
  • 场景三:公司负责开发对安全性要求极高的系统,由于时间紧张而篡改了安全的有效性验证记录,这时工程人员的职责是保守秘密,还是以一定的方式向客户披露交付的系统可能不安全?

上述情况中潜在的灾难、灾难的严重程度及灾难的受害者这些因素都将影响决定的做出。如果情况非常危险,就应该通过一定的方式披露出来,但这时还应该同时尊重雇主的权利。

软件工程人员必须坚持诚实正直的行为准则,他们不能用掌握的知识和技能做不诚实的事情,更不能给软件工程行业抹黑。然而在有些方面,某些行为没有法律加以规范,只能靠职业道德来约束。在这一方面职业协会和机构肩负重任。ACM、IEEE(电气和电子工程师协会)和英国计算机协会等组织颁布了职业行为准则或职业道德准则,凡是加入这些组织的成员必须严格遵守。

第二章 软件过程

  • 什么是软件过程
  • 软件过程中有哪些通用的框架活动。
  • 了解各种类型的软件过程模型及其优点与缺点,以及适用的开发场景。

软件过程概述

在开发产品或构建系统中,遵循的一系列可预测的步骤(即路线图)就称为「软件过程」。

软件过程提高了软件工程活动的稳定性、可控性、有组织性。但现代软件工程方法必须是灵活的,也就是要求软件工程活动、控制及工作产品适合于项目团队和将要开发的产品。

  • 以下四种基本活动对软件工程来说是必需的,它们也是软件生命周期中最主要的活动。
    • 软件描述:必须定义软件的功能及软件操作上的约束。
    • 软件设计和实现:必须生产符合描述的软件。
    • 软件有效性验证:软件必须得到有效性验证,即确保软件是客户所想要的。
    • 软件进化:软件必须进化以满足不断变化的客户需要。

软件描述

软件描述阶段是软件项目的早期阶段,主要是由软件分析人员和用户合作,针对有待开发的软件系统进行分析规划和规格描述,确定软件做什么,为今后的软件开发做好准备。

需求工程是软件过程中的一个特别关键的阶段,需求工程过程的目标是生成一个达成一致意见的需求文档,定义能满足客户需求的系统。通常文档中要表达出两个层次的需求:最终用户和客户需要高层的用户需求描述;系统开发人员需要比较详细的系统描述。

  • 需求工程过程有以下四个主要的阶段。
    • 可行性研究:指明现有的软件、硬件技术能否实现用户对新系统的要求,从业务角度决定系统开发是否划算,以及在预算范围内能否开发出来。最后得出结论,该系统是否值得进行更细致的分析。结果以「可行性研究报告」形式提交。
    • 需求导出和分析:通过对现有系统分析、与潜在用户和购买者讨论、进行任务分析等导出系统需求的过程。也可能需要开发一个或多个不同的系统模型和原型,来导出用户真正的需求,这些都会帮助分析员了解所要描述的系统。
    • 需求描述:把在分析活动中收集的信息以需求文档的形式确定下来。文档中有两类需求:用户需求是从客户和最终用户的角度对系统需求的抽象描述;系统需求是对系统要提供的功能、性能、操作、数据等多方面的详尽描述。
    • 需求有效性验证:检查需求的现实性、一致性、完备性。改正需求文档中的错误,结果将得到与用户达成一致意见的「软件需求规格说明书」,其结论不仅是今后软件开发的基本依据,同时也是用户对软件产品进行验收的基本依据。

需求过程中的各项活动并不是严格按顺序进行的。在定义和描述期间,需求分析继续进行,在整个需求工程过程中不断有新的需求出现。因此,分析、定义和描述是交替进行的。

软件设计与实现

  1. 软件设计
    • 软件设计是对实现系统的结构、系统的数据、系统构件间的接口,以及所用的算法的描述。这是一个多次反复的过程。在设计过程中要不断添加设计要素和设计细节,并对之前的设计方案进行修正。
    • 设计过程中的活动是交替进行的,从一个阶段到另一个阶段的反馈及其引发的返工在所有的设计过程中都是不可避免的。
    • 设计输入
      • 平台信息:软件平台是软件执行的环境,设计人员必须考虑怎样使系统与软件环境集成得最好,因此平台信息是设计过程的基本输入。
      • 需求描述:是软件必须实现的功能、性能和可靠性要求的说明。
      • 数据描述:大部分的系统都是对数据的输入、处理、输出,因此对数据的描述就显得尤为重要。
    • 设计过程活动:不同类型的系统设计过程中的活动会有所不同,以下为信息系统设计过程中的 4 个基本活动。
      • 体系结构设计:识别系统总体结构、基本构件(组件、子系统或模块)之间的关系,以及它们是怎样分布的,并且可以确定哪些构件是可以复用的。
      • 接口设计:定义系统构件间的接口。接口的描述必须是无二义性的。在有精确接口定义的前提下,构件不必知道其他构件的具体实现即可使用它们。一旦接口描述达成一致意见,构件就可以并行设计和开发了。
      • 构件设计:针对每个系统构件设计它的运行方式。其是对构件基于某个细化的设计模型所做的一系列的详细设计。设计模型可用于自动生成一个实现代码框架。
      • 数据库设计:设计系统数据结构,以及如何在数据库中表示这些数据结构。此处的工作又一次取决于是否复用现有数据库或创建一个新的数据库。
    • 设计输出:上述活动产生一组设计输出,这些输出的细节和表现有很大不同,对于要求极高的系统必须要有详细的设计文档给出简洁和准确的描述,以「概要设计说明书」和「详细设计说明书」的形式提交。
      • 用模型驱动方法,这些输出可能大多数是图形
      • 用敏捷开发方法,设计过程的输出可能不会有单独的描述文档,而是在程序代码中直接表示
      • 结构化设计方法和UML面向对象的设计方法都是典型的模型驱动方法,它们依赖于创建系统的图形模型,模型设计得越充分详细,生成系统得代码框架越贴合系统需求。
  2. 软件实现
    • 系统设计过程之后就是实现系统的程序开发过程。安全性能要求极高的系统在系统任何实现进行之前需要完成所有的详细设计,但一般情况下,后续的设计阶段和程序开发是交织在一起的。
    • 详细的设计模型可以极大减少编码的工作量,通过软件模型可以从一个设计直接得到一个程序的框架,其中包括定义和实现界面的代码。大多数情况下,开发人员只需要增加每个程序构件的工作细节即可。
    • 程序设计没有统一的模式。
    • 程序设计人员要对自己开发的程序进行测试,这可以暴露一些程序中的明显错误,纠正这些错误的过程叫调试。
    • 错误检测和程序调试不是一回事,检测是发现存在的错误,而调试是要定位并改正这些错误。程序员进行程序调试首先要对程序的行为有一个最初的预期,然后执行程序看输出结果是否同预期一样。调试过程需要程序员一步一步地手动跟踪代码,同时会需要一些测试用例来定位问题。一些交互式调试工具,能够显示程序中变量的中间结果,也能跟踪程序的执行语句,可以用来支持程序的调试过程。

软件有效性验证

软件有效性验证,是要看系统是否符合它的描述及系统是否符合客户的预期。

测试过程中的阶段包括:系统构建测试、系统集成测试、接收测试。一旦缺陷被发现,程序就需要进行调试,这又会引起一系列测试阶段的反复。有的构件的错误只有当集成时才暴露出来,因此,这个过程是一个反复的过程,不断会有信息从后继阶段反馈到前面的阶段。

  • 构件(或单元)测试:对组成系统的构件进行测试。每个构件都单独测试而不受其他系统构件的影响。构件可能是简单的实体,如一个函数或对象类,或者是这些实体的一个相关集合。
  • 系统测试:集成构件形成完整的系统。这个过程主要是关注无法预测的构件间交互和构件界面问题所引发的错误,也关注系统是否满足了功能上和非功能上的需求,并测试系统的总体特性。对于大型系统来说,这可能是一个多阶段的过程,需要对构件所构成的子系统进行测试,然后测试由这些子系统构成的最终系统。
  • 接收测试:这是系统在接收并运行之前进行的最后阶段测试。这个阶段不再使用模拟数据,而是用客户提供的真实数据测试系统。真实数据能暴露出系统需求定义中的错误和遗漏。接收测试还能发现系统需求中的类问题,即系统功能不能满足用户的需求或者系统性能是无法接收的。
    • 当定制系统是为特定客户开发的,接收测试有时称为「alpha测试」,使开发人员和客户双方都承认交付的系统是满足最初的需求定义的。
    • 当一个系统要作为软件产品在市场上销售时,所要进行的测试称为「beta测试」。「beta测试」就是将系统交付给所有愿意使用该系统的潜在客户。他们有义务报告系统中的问题,以使产品面向实际使用,「beta测试」能暴露系统开发人员无法预见的错误。通过这个反馈,系统被修改并且发布另外一个测试版本或正式销售版本。

软件进化

软件进化的任务是保障软件的正常运行及对软件进行维护更新。

为了排除软件系统中可能隐含的错误,适应用户需求及操作系统环境的变化,需要继续对系统进行修改或扩充。为使系统具有较强的生命力,对于每一项维护活动都应准确地记录下来,作为正式的文档资料加以保存。在适当的时候要对软件进行评价,如果经过修改或补充,软件仍不能适应新的需求,则该软件就应该被新的软件所替代。

自有软件开发以来,就有软件开发过程和软件进化(软件维护)过程之分。人们通常认为软件维护是单调无趣的,虽然维护的成本经常是最初开发成本的数倍,但是维护过程通常不被认为有什么挑战性。现在看来这种划分越来越不恰当了。现在从头开始开发的系统很少,将软件系统的开发和维护看成是一个连续过程显得更有意义。因此,不再将软件工程分为开发和维护两个完全独立的过程,而是将其看成一个进化过程,即软件在其生命周期内不断地随着需求的变更而变更的进化式过程。

软件开发团队组成

软件开发过程中不同的阶段由不同职责的人员负责,而不同的项目所需要软件团队的组织是不同的。

  1. 系统分析员
    • 需求分析师:与客户交流,准确获取客户需求。是项目前期与客户方打交道最多的人,对于客户来说,他可以代表整个项目组,对于项目组成员来说,他的意见可以代表客户方的意见,项目组内所有与客户需求相关的事情都必须得到他的认可。
    • 系统分析师:对软件项目进行整体规划、需求分析、设计软件的核心架构、指导和领导项目开发小组进行软件开发和软件实现,并对整个项目进行全面的管理工作。他是项目的推动者,也是项目成功的关键。
    • 系统分析员:根据客户的需求写出以通过软件解决的软件需求及功能文档实现。
  2. 系统设计员
    • 系统架构师:负责设计系统整体架构,从需求到设计的每个细节都要考虑到,把握整个项目,使设计项目尽量效率高、开发容易、维护方便、升级简单等。系统架构师可以理解成技术总监。系统架构师是在部门内所有软件项目中,对技术上所有重要的事情做出决定的人。
    • 软件设计师:对与系统分析师和架构师所划分的构件进一步细化,保障每个构件按既定的标准和要求完成。
  3. 软件实现员
    • 软件开发工程师(程序员):根据设计师的设计成果进行具体编码工作,对自己的代码进行基本的单元测试。软件开发工程师是最终实现代码的成员。
    • 数据库设计师:又称DBA,根据业务需求和系统性能分析、建模,设计数据库,完成数据库操作,确保数据库操作的正确性、安全性。他是项目组中唯一能对数据库进行直接操作的人,也是对项目中与数据库相关的所有重要的事情做最终决定的人。
    • UI设计:负责软件的界面设计与制作。
    • 美工:负责公司软件产品的美工设计。
  4. 测试员
    • 系统测试工程师:对最终软件产品进行全面测试,确保最终软件系统满足产品需求,并且遵循系统设计。在系统测试前制订全面的测试计划,测试后提供完整的测试报告,保证其完整性资格要求。
  5. 软件部署员
    • 系统集成工程师:指进行数据库的安装和维护,进行数据平台的安装、配置和使用等各种应用服务器的安装和配置人员。其主要工作内容包括硬件集成、系统初始化、系统配置、软件安装、系统性能优化等。
  6. 项目管理员
    • 项目经理:负责人员安排和项目分工,对项目的各个阶段进行验收,对项目参与人员的工作进行考核,管理项目开发过程中的各种文档,直接对公司领导层负责。是在整个项目开发过程中项目组内对所有非技术性重要事情做出决定的人。
    • 项目组长:通常三四个开发人员组成一个开发小组,有一个小组负责人带领进行开发活动,由小组内技术和业务比较好的成员担任。

软件过程模型概述

为了能高效地开发出高质量的软件产品,通常把软件过程中各项开发活动的流程用一个合理的框架——开发模型来规范描述,这就是软件过程模型。

软件过程模型

瀑布模型(Waterfall Model) 又称为 经典生命周期(Classic Life Cycle)

瀑布模型的一个变体称为 V模型(V-model)。V模型描述了测试计划同需求定义、系统设计及代码生成等相关的动作之间的关系。

  • 随着软件团队工作沿着V模型左侧步骤向下推进,基本问题需求逐步细化,形成了对问题及解决方案的详尽且技术性的描述。
  • 一旦编码结束,团队沿着V模型右侧的步骤向上推进工作,其本质上是执行了一系列的测试(质量保证),这些测试验证了V模型左侧所生成的每个模型。
  • 实际上,经典生命周期模型和V模型没有本质区别,V模型提供了一种将验证和确认动作应用于早期软件工程工作中的直观方法。

瀑布模型是软件工程最早的范例。在运用它的过程中人们遇到的问题包括:

  • 实际项目很少遵循瀑布模型提出的顺序。
  • 客户通常难以清楚地描述所有的需求,而瀑布模型却要求客户明确需求,很难适应在许多项目开始阶段必然存在的不确定性。
  • 客户必须要有耐心,因为只有在项目接近尾声时他们才能得到可执行的程序。如果在可执行程序评审之前没有发现系统中存在的重大缺陷,将可能造成惨重损失。
  • 经典生命周期模型的线性特性在某些项目中会导致「阻塞状态」,由于任务间的依赖性,开发团队中的一些成员要等待另一些成员工作完成。花在等待上的时间可能超过花在生产性工作上的时间。在线性过程中的开始和结束,这种阻塞状态更易发生。

因此适合采用瀑布模型的情况通常发生在:

  • 需要对某个已经存在的系统进行明确定义的适应性调整或是增强的时候(如政府修改了法规,导致财务软件必须进行相应修改)。
  • 新的开发项目(需求可以准确定义和相对稳定的)。
  • 开发人员对目标和应用领域很熟悉。

由于瀑布模型反映了在其他工程项目中使用的一类过程的模型,并且在整个项目中它很容易结合通用的管理模式进行管理,基于该方法的软件过程仍然广泛应用于软件开发。

增量过程模型

在初始软件需求有明确定义的情况下,迫切需要提供一套功能有限的软件产品给用户使用并听取用户的使用意见和建议,在后续版本中再进行细化和扩展功能,直到产生一个充分的系统。在这种条件下,需要选用一种增量的形式生成软件产品的过程模型。

  • 增量模型综合了线性过程流和并行过程流的特征。随着时间的推移,增量模型在每个阶段都运用线性序列,每个线性序列生产出软件的可交付增量。
  • 运用增量模型时,第1个增量往往是核心产品,也就是满足了最重要或最紧急的功能需求,不包含许多附加的特性,客户使用该核心产品并进行仔细评估,然后根据评估结果制订下一个增量计划。这份计划应说明需要对核心产品进行的修改,以便更好地满足客户的要求,也应说明需要增加的特性和功能。每一个增量的交付都会重复这一过程,直到最终产品的产生。
  • 如果客户要求在一个不可能完成的时间提交软件,那么可以向他建议届时只提交一个或几个增量,此后再提交软件的其他增量。

增量式开发与瀑布模型比较有以下主要优点:

  • 降低了适应用户需求变更的成本。重新分析和修改文档的工作量较之瀑布模型要少很多。
  • 在开发过程中更容易得到用户对于已开发工作的反馈意见。用户可以评价软件的现实版本,并可以看到已经实现了多少,方便用户判断工程进度。
  • 更快地交付和部署有用的软件。用户可以更早地使用软件并创造商业价值。

增量模型也存在一个很大的问题:

  • 伴随着新的增量的添加,系统结构在逐渐退化。
  • 除非投入时间和金钱在重构系统结构上以改善软件,否则定期的变更会损坏系统的结构。
  • 随着时间的推移越往后变更系统越困难,而且成本也将逐渐上升。

大型系统需要一个稳定的框架或体系结构,而负责开发不同部分的团队需要根据体系结构明确指定其职责。这需要提前制定计划,而不是增量的开发。

构件复用模型

对象技术将事物实体封装成包含数据和数据处理方法的对象,并抽象为类。经过适当的设计和实现的类或类的集合也可称为构件。

由于构件具有一定的通用性,因此可以在不同的软件系统中被复用,在基于构件复用的软件开发中,软件由构件装配而成。构件复用技术能带来更好的复用效果,并且具有工程特性,更能适应软件按照工业流程生产的需要。

构件复用模型的工作流程(以构件复用为驱动)

构件复用模型主要包含以下几个阶段的任务:

  1. 需求框架描述。描述软件系统功能构成,并将各项功能以设定的构件为单位进行区域划分。
  2. 构件复用分析。按照需求框架中的构建成分,分析哪些构件是现成的,哪些构件可以买到,哪些构件需要自己开发。
  3. 需求修改与细化。以提高对现有构件的复用和降低新构件开发为目的,调整需求框架,并对已经确定的需求框架进行细化,由此获得对软件系统的详细需求定义。
  4. 系统设计。基于构件技术设计系统框架,设计需要开发的新构件。
  5. 构件开发。开发不能获得复用的新构件。
  6. 系统集成。根据设计要求,将诸多构件整合在一起构成一个系统。

构件复用模型最明显的优势是:

  • 减少了需要开发的软件数量
  • 缩短软件交付周期
  • 提高了软件的质量
  • 降低了开发风险

它的成功主要依赖于有可以使用的、复用的构件,以及集成这些构件的系统框架。

应对变更

在开发过程中,商业和产品需求经常发生变化,变更增加软件开发的成本,这通常意味着已经完成的工作要重做,这将直接导致最终产品难以实现。软件开发人员需要一种专门应对变更的软件产品的过程模型。

原型模型

有的时候,客户定义了软件的一些基本任务,但是没有详细定义功能和特性需求,而当开发人员对算法的效率、操作系统的适用性和人机交互的形式等情况并没有把握时,在这些情况和类似情况下采用原型开发模型是最好的解决方法。

  • 首先,软件开发人员与客户进行沟通,定义软件的整体目标,明确已知的需求,并大致勾画出以后,再进一步定义内容。
  • 其次,软件开发人员快速设计产生一个原型让用户使用,然后根据用户使用情况的意见反馈,对原型不断修改,使开发人员逐步清楚用户的需求。
  • 这即是典型的「迭代」过程。
  • 原型的构建不一定非要是可执行的程序,基于模型系统的用户界面也可以有效地帮助用户细化界面设计,尽管许多原型系统是临时系统并且会被抛弃,但其他一些原型系统会演化为实际系统。

1.抛弃式原型

  • 快速建立一个反映用户主要需求的原型系统,让用户在计算机上试用它,之后根据用户提出的修改意见,修改原型系统,直到用户满意。
  • 抛弃式原型用途为:获取用户的真正需求,一旦需求确定,原型将被抛弃,然后再按线性流程进行实际项目的开发。

抛弃式原型的优点主要有:

  • 通过原型准确获取用户需求,在开发过程的后续阶段不会因为前期需求错误而进行较大的返工。
  • 开发人员通过原型系统已经知道系统应该做什么,因此设计和编码阶段发生错误的可能性比较小。

抛弃式原型的缺点主要有:

  • 对于一个大型复杂的系统,如果不经过分析来进行整体性划分,想直接用屏幕来一个一个地模拟是很困难的。
  • 对于大量运算、逻辑性较强的程序模块,抛弃式模型很难构造出模型供客户评价。

抛弃式原型只适用于小型、简单、处理过程比较明确、没有大量运算和逻辑处理过程的系统。

2.进化式原型

  • 进化式原型对开发过程的考虑是,针对有待开发的软件系统,先开发一个原型系统让用户使用,然后根据用户使用情况的意见反馈,对原型系统不断修改,使它逐步接近并最终达到开发目标。
  • 与抛弃式原型不同的是,进化式原型所要创建的原型是一个今后要投入应用的系统,只是所创建的原型系统在功能、性能等方面还有许多不足,还没有达到最终的开发目标,需要不断改进。

进化式原型是通过不断发布新的软件版本而使软件逐步完善的,因此,这种开发模型特别适合于用户急需的软件产品开发。它能够快速地向用户交付可以投入实际运行的软件成果,并能够很好地适应软件用户对需求规格的变更。

进化式原型要面临如下几个问题:

  • 不可能调整原型以满足非功能性的要求,如性能、安全性、鲁棒性和可靠性需求。这些都会在原型开发时被忽略。
  • 开发过程中的快速更改必然意味着原型是没有文档的。唯一的设计描述就是原型的代码,这不利于长期的维护。
  • 原型开发过程中的变更可能会破坏系统的结构。系统的维护将会很困难,而且很昂贵。
  • 在原型开发中机构的质量标准通常是被放松了的。
螺旋模型 (风险驱动软件过程框架)

螺旋模型是瀑布模型与原型进化模型相结合,并增加了风险分析而建立的一种软件过程模型。该模型适合于指导大型软件项目的开发,它将软件项目开发划分为制订计划、风险分析、实施开发及客户评估四类活动。

软件风险是任何软件开发项目中普遍存在的问题,不同项目只是风险大小不同而已。在制订项目开发计划时,系统分析员需要回答项目的需求是什么、投入多少资源、如何安排开发进度等问题后才能制订计划。而仅凭经验或初步设想来回答这些问题,难免会带来一定风险。项目规模越大、问题越复杂,资源、成本、进度等因素的不确定性就越大,承担项目所冒的风险也越大。人们进行风险分析与管理的目的就是在造成危害之前及时对风险进行识别、分析、采取对策,从而消除或减少风险所造成的损失。

项目进程沿着螺旋模型旋转
  • 制订计划。确定软件目标,选定实施方案,弄清项目开发限制条件。
  • 风险分析。分析所选方案,考虑如何识别和消除风险。
  • 实施开发。实施软件开发。
  • 用户评估。评价开发工作,提出修正建议。

项目进程沿着螺旋线每旋转一圈,表示开发出一个较前一个版本更加完善的新软件版本。例如,在第一圈确定了初步的目标、方案和限制条件后,转入右上象限,对风险进行识别和分析。如果开发风险过大,开发人员和用户无法承受,项目有可能因此而终止。多数情况下会沿着螺旋线继续下去,由内向外逐步延伸,最终得到满意的软件。如果对所开发项目的需求有了较好的理解或需求基本确定,无须开发原型,便可采用普通的瀑布模型。这在螺旋模型中被认为是单圈螺线。与此相反,需要开发原型,甚至需要不止一个原型的帮助时,那就要经历多圈螺线。

  • 螺旋模型的优越性:它吸收了「进化」的概念,使得开发人员和用户对每一个演化层出现的风险均有所了解并对此做出反应。
  • 但使用该模型需要丰富的风险评估经验和专门的知识,如果项目风险较大又未及时发现,势必造成重大损失。
  • 实际上,对软件项目进行风险分析也需要费用,假如项目风险分析费用过高,甚至超过了项目的开发费用,显然就不合适了。
  • 一般大型项目才有较高的风险,才有进行详细风险分析的必要。因此,这种模型比较适合大型的软件项目。

Rational 统一过程

软件统一开发过程 (Rational Unified Process, RUP) 是基于面向对象统一建模语言(UML)的一种面向对象的软件过程模型。RUP是一个通用的过程框架,可用于各种不同类型的软件系统、各种不同的应用领域和不同规模的项目。

RUP的突出特点是由用例驱动,以架构为核心,采用迭代和增量的开发策略

用例描述了用户对系统功能的需求,用于驱动的目的是使开发过程中的每个阶段都可以回溯到用户的需求。以系统架构为核心是指必须关注体系结构模型的开发,保证开发的系统能平滑无缝地进行。RUP中对迭代的支持有两种方式:①每一个阶段可能被迭代地执行,其结果一次次增量式地得到改善。②所有阶段作为一个整体也会增量式地执行。

RUP是一个阶段化的模型,识别出软件过程中的4个独立阶段。然而,不像瀑布模型各个阶段与过程活动是等同的,RUP最重要的创新在于把阶段和工作流相分离,以及强调将软件部署到用户环境中的重要性。RUP的4个基本阶段如下:

  1. 初始阶段(Inception Phase)
    • 初始阶段的目标是为系统建立业务用例和确定项目的边界。
    • 为了达到该目的必须识别所有与系统交互的外部实体,在较高层次上定义交互的特性,需要识别所有用例和描述一些重要的用例,通过与利益相关者协作定义软件的业务需求,提出系统大致的架构,并制订开发计划以保证项目开发具有迭代和增量的特性。
    • 初始阶段主要是定义验收规范、风险评估、所需资源估计,体现主要里程碑预期的阶段计划等。
  2. 细化阶段(Elaboration Phase)
    • 细化阶段的目标是分析问题域,建立健全体系结构基础,淘汰项目中风险最高的元素。
    • 细化阶段扩展初始阶段定义的用例和体系结构,以分析设计为重点,得到系统用例模型、需求模型、设计模型、实现模型和部署模型。
    • 在某些情况下,细化阶段建立了一个可执行的「体系结构基线」,这是建立可执行系统的第一步,体系结构基线证明了体系结构的可实现性,但没有提供系统使用时所需要的所有功能和特性,另外,在细化的最终阶段将评审项目计划以确保项目的范围、风险和交付日期的合理性。
    • 该阶段通常要对项目计划进行修订。
  3. 构建阶段(Construction Phase)
    • 构建阶段的目标是开发所有构件和应用程序,把它们集成为客户需要的产品,并且详尽测试所有功能。
    • 在这个阶段完成时,就得到了一个能工作的软件系统,以及能交付给用户的相关文档。
  4. 转换阶段(Transition Phase)
    • 转换阶段是RUP的最后阶段,软件被提交给最终用户进行Beta测试,在用户真实的使用环境下,使用真实的用户数据进行测试,用户反馈报告缺陷及必要的变更。
    • 另外,软件开发团队创建系统发布所必需的支持信息(如用户手册、问题解决指南及安装步骤)。
    • 在转换阶段结束时,软件增量成为可用的发布版本。

在以上过程中,RUP定义了6个核心过程工作流,3个核心支持工作流。核心过程工作流和核心支持工作流的描述如图所示。

  1. 核心过程工作流
    • 业务建模:使用业务用例对业务过程进行建模。
    • 需求:找出与系统进行交互的参与者并开发用例完成对系统需求的建模。
    • 分析与设计:使用体系结构模型、构件模型、对象模型和时序模型来创建并记录设计模型。
    • 实现:实现系统中的构件并将它们合理组织在子系统中。从设计模型自动地生成代码有助于加快此过程。
    • 测试:测试是一个迭代过程,它的执行是与实现紧密相连的。系统测试紧随实现环节的完成。
    • 部署:创建和向用户分发产品版本并安装到工作场所。
  2. 核心支持工作流
    • 配置和变更管理:此支持性工作流用于管理对系统的变更。
    • 项目管理:此支持性工作流用于管理系统开发。
    • 环境:此工作流用于提供软件开发团队可用的合适的软件工具。

每个阶段都有多次迭代,每次迭代只根据系统架构考虑系统的一部分需求,针对这部分需求进行分析、构件设计、实现、测试和部署的工作,每次迭代都是在系统已完成部分的基础上进行的,每次给系统增加一些新的功能,如此循环往复下去,直至完成最终项目。

敏捷软件开发

敏捷方法适合于需求萌动、快速改变的小型或中型的软件产品,以及开发团队人员数量较少、组织紧密结合的团队,而不太适合安全性、可靠性要求极高的大型系统。

在系统维护上,关键文档是系统需求文档,它明确定义软件系统应该做什么,如果没有这些信息,将很难评估所建系统的变更影响。许多敏捷方法非正式地、增量式地收集需求,没有建立有条理的需求文档。为此,使用敏捷方法很可能使随后的系统维护变得更难、更昂贵。

敏捷联盟为希望达到敏捷的人们定义了以下12条原则:

  1. 我们最优先要做的是通过尽早、持续交付有价值的软件来使客户满意。
  2. 即使在开发的后期,也欢迎需求变更。敏捷过程利用变更为客户创造竞争优势。
  3. 经常性地交付和运行软件,交付的时间间隔可以从几个星期到几个月,越短越好。
  4. 在整个项目开发期间,业务人员和开发人员必须每天都在一起工作。
  5. 围绕有积极性的个人构建项目,给他们提供所需的环境和支持,并且信任他们能够完成工作。
  6. 在团队内部,最富有效果和效率的信息传递方式是面对面交谈。
  7. 可运行软件是进度的首要度量标准。

参考资料

[1] 梁洁, 金兰. 软件工程实用案例教程[M]. 北京:清华大学出版社, 2019.

这篇文章有用吗?

点击星号为它评分!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位评论此文章。

很抱歉,这篇文章对您没有用!

让我们改善这篇文章!

告诉我们我们如何改善这篇文章?

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注