软件工程课程笔记 (1)
软件工程
软件和软件危机
软件
软件是计算机系统中与硬件相互依存的另一部分,它是包括程序、数据及其相关文档的完整集合。其中:
- 程序是按事先设计的功能和性能要求执行的指令序列
- 数据是使程序能正常操纵信息的数据结构
- 文档是与程序开发、维护和使用有关的图文材料
软件是一种逻辑实体,而不是具体的物理实体,因而它具有抽象性。
软件的生产与硬件不同,在它的开发中没有明显的制造过程。对软件的质量控制,必须着重在软件开发方面下功夫。与硬件不同,软件在运行和使用期间,没有机械磨损、老化问题。
关于 Bugs 的术语
- human mistake、error(错误):指软件开发中的人为出错
- fault(错误、缺陷、瑕疵):人为错误所导致的工作产品缺陷
- failure(故障、失效):对用户而言,指相对于系统预期行为的偏离
软件的发展
| 特点 | 程序设计阶段 (50至60年代) | 程序系统阶段 (60至70年代) | 软件工程阶段 (70年代以后) |
|---|---|---|---|
| 软件所指 | 程序 | 程序及说明书 | 程序、文档、数据 |
| 主要程序设计语言 | 汇编及机器语言 | 高级语言 | 软件语言(如需求定义语言等) |
| 软件工作范围 | 程序编写 | 包括设计和测试 | 软件生命周期 |
| 需求者 | 程序设计者本人 | 少数用户 | 市场用户 |
| 开发软件的组织 | 个人 | 开发小组(软件作坊) | 开发小组及大中型软件开发机构 |
| 软件规模 | 小型 | 中小型 | 大中小型 |
| 决定质量的因素 | 个人程序技术 | 小组技术水平 | 管理水平 |
| 开发技术和手段 | 子程序和程序库 | 结构化程序设计 | 数据库、开发工具、开发环境、工程化开发方法、标准和规范、网络及分布式开发、面向对象技术 |
| 维护责任者 | 程序设计者 | 开发小组 | 专职维护人员 |
| 硬件特征 | 价格高,存储容量小,工作可靠性差 | 降价、速度、容量及工作可靠性 有明显提高 | 向超高速、大容量、微型化及网络化方向发展 |
| 软件特征 | 完全不受重视 | 软件技术的发展 不能满足需要,出现软件危机 | 开发技术有进步,但未获突破性进展,价高,未完全摆脱软件危机 |

软件危机
在程序系统阶段,软件技术的发展不能满足需要,“软件危机”就这样出现了。软件危机是指:**在计算机软件的开发和维护过程中所遇到的一系列严重问题。**几乎所有软件都不同程度地存在这些问题。
大体上,这些问题分为两方面:
- 如何开发软件,以满足对软件日益增长的需求
- 如何维护数量不断膨胀的已有软件
软件危机的主要表现是:
- 软件成本在计算机系统总成本中所占的比例逐年上升
- 软件开发生产率提高的速度,远远跟不上计算机应用迅速普及深入的趋势
软件质量度量是用可量化的数据来评估软件质量特性的过程。
其中 是软件质量要素 对第 种评价准则的测量值, 是相应的加权系数。
McCall 的软件质量模型将要素主要分成:

主要要素有:
- 可审查性 (Auditability)
- 准确性 (Accuracy)
- 通信通用性 (Communication commonality)
- 完全性 (Completeness)
- 简明性 (Conciseness)
- 一致性 (Consistency)
- 数据通用性 (Data Commonality)
- 容错性 (Error-tolerance)
- 执行效率 ( Execution Efficiency)
- 可扩充性 (Expandability)
- 通用性 (Generality)
- 硬件独立性 (Hardware Independence)
- 检测性 (Instrumentation)
- 模块化 (Modularity)
- 可操作性 (Operability)
- 安全性 (Security)
- 自文档化 (Self-documentation)
简单性 (Simplicity) - 软件系统独立性 (Software System Independence)
- 可追踪性 (Tracebility)
- 易培训性 (Training)
软件危机的成因
一方面是由于软件本身的特点:
- 软件的逻辑性
- 程序的复杂性、规模庞大
另一方面是由于软件开发与维护的方法不正确:
- 忽视软件定义时期的工作, 特别是忽视了软件需求分析的重要性 (在软件开发的不同阶段进行修改付出的代价是很不相同的)
- 认为软件开发就是写程序并设法使之运行
- 轻视软件维护

差错传播的模型
软件神话
软件神话指的是人们在软件开发中长期形成的、但实际上是错误或误导性的观念。
主要可分为三类:
- 管理者:
- 我们已经有了关于建造软件的标准和规程的书籍,难道它们不能给人们提供所有其需要知道的信息吗?
- 我们已经有了很多很好的软件开发工具,而且,我们为它们购买了最新的计算机。
- 如果我们已经落后于计划,可以增加更多的程序员来赶上进度。
- 用户:
- 有了对目标的一般描述就可以开始写程序了——我们可以以后再补充细节。
- 项目需求总是在不断变化,但这些变化能够很容易的满足,因为软件是灵活的。
- 开发者:
- 一旦我们写出了程序并使其正常运行,我们的工作就结束了。
- 在程序真正运行之前,没有办法评估其质量。
- 一个成功项目唯一应该提交的就是运行程序。
消除软件危机
首先应该对计算机软件有一个正确的认识:它是包括程序、数据及其相关文档的完整集合。
必须充分认识到软件开发不是某种个体劳动的神秘技巧,而应该是一种组织良好、管理严密、各类人员协同配合、共同完成的工程项目。
必须充分吸取和借鉴人类长期以来从事各种工程项目所积累的行之有效的原理、概念、技术和方法,特别要吸取几十年来人类从事计算机硬件研究和开发的经验教训。
应该推广使用在实践中总结出来的开发软件的成功的技术和方法,并且研究探索更有效的技术和方法,尽快消除在计算机系统早期发展阶段形成的一些错误观念和做法。
应该开发和使用更好的软件工具。
软件工程
面对软件危机,1968 年德国召开的一次 NATO 会议上首次签署声明“软件工程”这一说法,认为软件工程应当使用业已建立的工程学科的基本原理和范型。
背后驱使的观念是:软件设计、实现和维护应当与传统工程学科具有同等地位。
软件工程的定义
建立并使用完善的工程化原则,以较经济的手段获得能在实际机器上有效运行的可靠软件的一系列方法
1993 年 IEEE 更全面更具体的定义,软件工程是:
- 把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件
- 研究上一条中提到的途径
软件工程学科涉及到为高效率地构建满足客户需求的软件系统所需的理论、知识和实践的应用
软件工程是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程
软件工程的本质特性
- 软件工程关注大型程序的构造
- 软件工程的中心课题是控制复杂性
- 软件经常变化
- 开发软件的效率非常重要
- 和谐地合作是开发软件的关键
- 软件必须有效地支持它的用户
- 软件工程领域中是由具有一种文化背景的人替具有另一种文化背景的人创造产品
软件工程的基本原理
著名的软件工程专家 B. W. Boehm 于 1983 年提出了软件工程的七条基本原理。
他认为这七条原理是确保软件产品质量和开发效率的原理的最小集合:
- 用分阶段的生命周期计划严格管理
- 把软件生命周期划分成若干阶段,并相应制定出切实可行的计划,并严格按照计划对软件的开发与维护工作进行管理
- 坚持进行阶段评审
- 大部分错误是在编码之前造成的,例如,根据 Boehm 等人的统计,设计错误占软件错误的 63%,编码错误仅占 37%
- 错误发现与改正得越晚,所需付出的代价也越高
- 实行严格的产品控制
- 当改变需求时,为了保持软件各个配置成分的一致性,必须实行严格的产品控制,其中主要是实行基准配置管理
- 所谓基准配置又称为基线配置,它们是经过阶段评审后的软件配置成分(各个阶段产生的文档或程序代码)
- 基准配置管理也称为变动控制:一切有关修改软件的建议,特别是涉及到对基准配置的修改建议,都必须按照严格的规程进行评审,获得批准以后才能实施修改
- 采用现代程序设计技术
- 实践表明,采用先进的技术既可提高软件开发和维护的效率,又可提高软件产品的质量
- 结果应能清楚地审查
- 为了提高软件开发过程的可见性,更好地进行管理,应该根据软件开发项目的总目标及完成期限,规定开发组织的责任和产品标准,从而使得所得到的结果能够清楚地审查
- 开发小组的成员应该少而精
- 开发小组人员的素质和数量是影响软件产品质量和开发效率的重要因素
- 承认不断改进软件工程实践的必要性
- 不仅要积极主动地采纳新的软件技术,而且要注意不断总结经验,评价新的软件技术的效果,指明必须着重开发的软件工具和应该优先研究的技术
软件工程的基本内容
软件工程包括管理和技术两方面的内容。
管理就是通过计划、组织和控制等一系列活动,合理地配置和使用各种资源,以达到既定目标的过程。
软件工程方法学
通常把在软件生命周期全过程中使用的一整套技术方法的集合称为方法学(methodology),也称为范型(paradigm)。
软件工程方法学包含三个要素:方法、工具和过程。
- 方法:完成软件开发的各项任务的技术方法,回答“怎样做”的问题;
- 工具:软件工具为软件工程方法提供了自动或半自动的软件支撑环境;
- 如果这些工具能够集成起来,即一个工具产生的信息可被另一个工具使用时,称这样的支持软件开发的系统为 CASE(计算机辅助软件工程)
- 过程:是为了获得高质量软件所需要完成的一系列任务的框架,它规定了完成各项任务的步骤,将软件工程的方法和工具综合起来以达到合理、及时地进行软件开发的目的。它定义了:
- 方法使用的顺序;
- 要求交付的文档资料;
- 为保证质量和适应变化所需要的管理;
- 软件开发各个阶段完成的里程碑。
目前使用得最广泛的软件工程方法学分别是传统方法学和面向对象方法学。
传统方法学
传统方法学又称生命周期方法学或结构化范型。
采用结构化技术(结构化分析、结构化设计和结构化实现)来完成软件开发的各项任务,并使用适当的软件工具或软件工程环境来支持结构化技术的运用。
把软件生命周期的全过程划分为若干个阶段:
前一阶段是基础、前提;后一阶段是细化;
每一个阶段的开始和结束都有严格的标准;
在每一个阶段结束之前都必须进行正式严格的技术审查和管理复审;
优点是:
- 通过将软件生命周期划分成若干个阶段降低了整个软件开发过程的困难程度;
- 每个阶段结束前的严格审查保证了软件的质量,提高了软件的可维护性。
缺点是:
- 当软件规模庞大,或者对软件的需求是模糊的或会随时间而变化的时候,使用传统方法学开发软件往往不成功,而且维护起来仍然很困难。
- 原因:把原本密切相关的数据和操作人为地分离成了两个独立的部分,增加了软件开发与维护的难度。
面向对象方法学
面向对象方法学是一种以数据为主线,把数据和对数据的操作紧密地结合起来的方法。
面向对象方法学的4个要点:
- 把对象作为融合了数据及在数据上的操作行为的统一的软件构件
- 把所有对象都划分成类
- 按照父类与子类的关系,把若干个相关类组成一个类层次结构,位于下层的类继承了上层中某类的特点
- 对象彼此间仅能通过发送消息互相联系
“面向对象=对象+类+继承+通信”
面向对象方法学的出发点和基本原则,是尽量模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界解决问题的方法与过程,从而使描述问题的问题空间与实现解法的求解空间在结构上尽可能一致。它的优点是:
- 降低了软件产品的复杂性
- 提高了软件的可理解性
- 简化了软件的开发和维护工作
- 促进了软件重用
软件工程涉及的角色和人员
角色(Role)是一种职责对应关系。
通常情况下,软件工程涉及的人员分为三种角色:
- 客户(Customer):花钱开发软件系统的公司、组织或个人
- 开发者(Developer):为客户构建软件系统的公司、组织或个人
- 用户(User):最终使用该系统的人员
引发角色交叉的新情况:通用商业软件包(Commercial off-the-shelf, COTS )、转包(Subcontract)
软件工程和其他学科
软件工程应用计算机科学、数学和管理科学等原理,借鉴传统工程的原则、方法来创建软件,从而达到提高质量、降低成本的目的。其中:
- 计算机科学和数学用于构造模型、分析算法
- 工程科学用于制定规范、明确范型、评估成本、确定权衡
- 管理科学用于进度、资源、质量、成本等的管理
软件的生命周期
一般问题的解决过程:
- 问题的阐述:界定问题,用较宽的范围而不是细节来定义和描述待解问题
- 问题的分析:问题定义的提炼,把问题分成可以理解和处理的子问题,进而提供基本细节
- 寻找解法:收集问题的一组可能解法
- 判定:每一种可能解法的评估和比较,直至获得最佳解法
- 设计规格说明:对选中解法的细节描述
- 实现:由设计到构造出结果产品,包括把分解过的各部分综合成一个有机的整体
而如同任何事物一样,软件也有一个孕育、诞生、成长、成熟、衰亡、演化的生存过程。为了用工程化方式有效地管理软件的全过程,软件的生存过程也可以划分为好几个阶段,由此逐步形成“软件生命周期”(Software Life Cycle)的概念,它是一个从用户需求开始,经过开发、交付使用,在使用中不断增补修订,直至让位于新软件的全过程;概括地说,软件生命周期由软件定义、软件开发和运行维护 3 个时期组成,每个时期又进一步划分成若干个阶段。
软件定义时期
- 问题定义阶段:界定问题的范围,确切地定义问题;
- 可行性研究阶段:研究问题的范围,探索这个问题是否值得去解,是否有可行的解决办法;
- 需求分析阶段:确定目标系统必须具备哪些功能;
另外,要估计完成该项工程所需要的资源和成本,制定工程进度表。
软件开发时期
具体设计和实现在前一个时期定义的软件。
- 总体设计阶段:设计出实现目标系统的几种可能的方案,权衡利弊推荐一最佳方案,并制定实现最佳方案的详细计划,以及设计软件的体系结构;
- 详细设计阶段:设计出程序的详细规格说明;
- 编码和单元测试阶段:写出正确的、容易理解、容易维护的程序模块;
- 综合测试阶段:通过各种类型的测试使软件达到预定的要求。集成测试/验收测试/现场测试/平行运行;
运行维护(软件维护)时期
这是时间最长的阶段。
维护阶段的关键任务是:通过各种必要的维护活动使软件系统持久地满足用户的需要。
通常的4种维护活动:
- 改正性维护:诊断和改正使用过程中发现的软件错误
- 适应性维护:修改软件以适应环境的变化
- 完善性维护:根据用户需要改进或扩充软件使之更完善
- 预防性维护:修改软件从而为将来的维护活动做好准备
软件开发团队中的角色
- 需求分析师:弄清客户想要什么
- 设计师:系统该如何去做
- 程序员:用代码实现设计师的想法
- 测试员:按照需求清单给系统挑毛病
- 培训人员:教用户如何使用系统
- 维护人员:这个角色可能包括上面所有角色
- 文档库管理员:组织和维护项目文档、记录软件的开发过程
- 配置管理小组:维护变更、控制变更、确保变更正确实现、报告变更
软件开发团队角色的承担视情况而定:
小项目中可能两三个人就承担所有的角色
大的项目中可能仅一个角色就需要由一个团队来承担
改变了软件工程实践的七大因素
- 紧迫的上市时间要求
- 硬件成本降低,开发和维护费用增高
- 桌面系统功能日益强大
- 网络的普及
- 面向对象方法与技术被广泛接受
- 图形用户界面的广泛使用
- 瀑布模型缺乏灵活性
软件过程
软件过程是为了获得高质量软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。
ISO 9000 对过程的定义:使用资源将输入转化为输出的活动所构成的系统。
瀑布模型

维护阶段的工作量占 70%,开发阶段的工作量占 30%,写代码占开发阶段的 20%(也就是总的 6%)
瀑布模型的特点
- 阶段间具有顺序性和依赖性
- 必须等前一阶段的工作完成之后,才能开始后一阶段的工作
- 前一阶段的输出文档就是后一阶段的输入文档
- 推迟实现的观点
- 清楚地区分逻辑设计与物理设计,尽可能推迟程序的物理实现
- 质量保证的观点
- 每个阶段都必须完成规定的文档,没有交出合格的文档就是没有完成该阶段的任务。
- 每个阶段结束前都要对所完成的文档进行评审,以便尽早发现问题,改正错误。
瀑布模型的优点
- 可强迫开发人员采用规范的方法(例如,结构化技术)
- 严格地规定了每个阶段必须提交的文档
- 要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证
瀑布模型的成功在很大程度上是由于它基本上是一种文档驱动的模型。
瀑布模型的缺点
- 要求用户不经过实践就提出完整准确的需求,在许多情况下都是不切实际的
- 仅仅通过写在纸上的静态的规格说明,很难全面正确地认识动态的软件产品
- 将本来非线性的软件开发过程人为地加以线性化,不符合实际中的软件开发情况
- 软件开发耗时长,可运行版本要等到项目后期才能得到,一旦在后期发现错误,付出的代价将是巨大的
“由文档驱动”的这个事实也是瀑布模型的一个主要缺点,这可能导致最终开发出的软件产品不能真正满足用户的需要。
V 模型

V 模型是瀑布模型的改进,强调测试活动与分析和设计之间的关联:
- 单元测试和集成测试 -> 校验程序设计;
- 系统测试 -> 校验(verify)系统设计;
- 验收测试 -> 确认(validate)需求;
与瀑布模型关注文档和工作产品不同,V 模型的关注点是软件开发各阶段的活动以及正确性,因此 V 模型是以活动驱动的。
- 验证(Verification)的目标是确定系统中各项功能可以正常工作,实质上是检查实现的质量如何。
- 确认(Validation)的目标是确定系统实现了全部的需求,确保开发方建造的是正确的、用户需要的产品。
V 模型的改良之处与存在的问题
- 本质是把瀑布模型中一些隐含的迭代过程明确出来,使开发活动和验证活动的相关性更加明显;
- V 模型使抽象等级的概念也更明显:所有从需求到实现部分的活动关注的是建立更多的系统详细表述,而所有从实现到交付运行的活动关注的是对系统的验证和确认。
- 和瀑布模型一样,都是对软件开发过程过份简单、理想化的抽象,对需求变化的适应性差。


