软件工程

一 软件工程概述

1.1 软件危机

1.1.1 软件危机的典型表现:

  • 对软件开发成本和进度的估计常常很不准确
  • 用户对“已完成的”软件系统不满意的现象经常发生
  • 软件产品的质量往往靠不住
  • 软件常常是不可维护的
  • 软件通常没有适当的文档资料
  • 软件成本在计算机系统总成本中所占的比例逐年上升
  • 软件开发生产率提高的速度,远远跟不上计算机应用迅速普及深入的趋势

1.1.2 产生软件危机的原因

  • 与软件本身特点有关
    • 不同于硬件,管理和控制软件开发过程相当困难
    • 软件长时间运行可能会遇见在开发时期没有测出来的错误
    • 软件的规模庞大,而且程序的复杂性会随着程序规模的增加而呈指数上升
    • 没有完整准确的认识用户需求就着手开发软件
    • 对软件开发和维护的理解不清楚,在实践过程中采用了错误的方法和技术
    • 错误的认识和做法,如忽略软件需求分析的重要性,轻视软件维护等
  • 与软件开发和维护的方法不正确有关
    • 只重视程序而忽视软件配置其余成分
    • 开发人员在软件定义时期没有正确全面理解用户需求
    • 在软件开发的不同阶段进行修改有付出的代价不同

1.1.3 消除软件危机的途径

  • 首先对计算机软件有一个正确的认识
  • 充分认识到软件开发是各类人员协同配合,共同完成的工程项目
  • 推广使用在实践中总结出来的开发软件的技术和方法,并且研究和探索更好的技术和方法
  • 开发和使用更好的软件开发工具

1.2 软件工程

1.2.1 软件工程概述

​ 软件工程是指导计算机软件开发和维护的一门工程学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。

1.2.2 软件工程的基本原理

  • 用分阶段的生命周期计划严格管理
  • 坚持进行阶段评审
  • 实行严格的产品控制
  • 采用现代程序设计技术
  • 结果应能清楚的审查
  • 开发小组的人员应该少而精
  • 承认不断改进软件工程实践的必要性

1.2.3 软件工程方法学

  • 传统方法学

    传统方法学也称为生命周期方法学或结构化范型。它采用结构化技术(结构化分析、结构化设计和结构化实现)来完成软件开发的各项任务,并使用适当的软件工具或软件工程环境来支持结构化技术的运用

    特点:

    • 传统方法学把软件生命周期的全过程依次划分为若干个阶段,然后顺序地完成每个阶段的任务。
    • 每个阶段的开始和结束都有严格标准,对于任何两个相邻的阶段而言,前一阶段的结束标准就是后一阶段的开始标准。
    • 在每一个阶段结束之前都必须进行正式严格的技术审查和管理复审。
    • 审查的一条主要标准就是每个阶段都应该交出“最新式的”(即和所开发的软件完全一致的)高质量的文档资料,从而保证在软件开发工程结束时有一个完整准确的软件配置交付使用。
    • 采用生命周期方法学可以大大提高软件开发的成功率,软件开发的生产率也能明显提高。
    • 目前,传统方法学仍然是人们在开发软件时使用得十分广泛的软件工程方法学。
  • 面向对象方法学

    与传统方法相反,面向对象方法把数据和行为看成是同等重要的,它是一种以数据为主线,把数据和对数据的操作紧密地结合起来的方法

    基本原则:

    • 尽量模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的方法与过程,从而使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。

    优点:

    • 降低了软件产品的复杂性,提高了软件的可理解性,简化了软件的开发和维护工作。
    • 面向对象方法特有的继承性和多态性,进一步提高了面向对象软件的可重用性。

1.3 软件生命周期

软件生命周期由软件定义、软件开发和运行维护三个时期组成

  • 软件定义时期
    • 任务:
      • 确定软件开发过程必须完成的总目标
      • 确定工程的可行性
      • 导出实现工程目标应该采用的策略及系统必须完成的功能
      • 估计完成该工程需要的资源和成本,制定工程进度表
    • 阶段:
      • 问题定义
      • 可行性研究
      • 需求分析
  • 软件开发时期
    • 阶段:
      • 总体设计
      • 详细设计
      • 编码
      • 单元测试、综合测试
  • 软件维护时期

1.4 软件过程

软件过程是为了获得高质量软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。

软件过程描述为了开发出客户需要的软件,什么人(who)、在什么时候(when)、做什么事(what)以及怎样(how)做这些事以实现某一个特定的具体目标。

1.4.1 瀑布模型

  • 特点
    • 阶段间具有顺序性和依赖性,必须等前一阶段的工作完成之后,才能开始后一阶段的工作;前一阶段的输出文档就是后一阶段的输入文档,因此,只有前一阶段的输出文档正确,后一阶段的工作才能获得正确的结果。
    • 推迟实现的观点,瀑布模型在编码之前设置了系统分析与系统设计的各个阶段,分析与设计阶段的基本任务规定,在这两个阶段主要考虑目标系统的逻辑模型,不涉及软件的物理实现。
    • 质量保证的观点,每个阶段都必须完成规定的文档,没有交出合格的文档就是没有完成该阶段的任务;每个阶段结束前都要对所完成的文档进行评审,以便尽早发现问题,改正错误。
  • 优点
    • 可强迫开发人员采用规范的方法
    • 严格地规定了每个阶段必须提交的文档
    • 要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证

1.4.2 快速原型模型

  • 特点
    • 软件产品的开发基本上是线性顺序进行的

1.4.3 增量模型

使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试。每个构件由多个相互作用的模块构成,并且能够完成特定的功能。使用增量模型时,第一个增量构件往往实现软件的基本需求,提供最核心的功能。

  • 优点
    • 能在较短时间内向用户提交可完成部分工作的产品
    • 逐步增加产品功能可以使用户有较充裕的时间学习和适应新产品,从而减少一个全新的软件可能给客户组织带来的冲击
  • 困难
    • 在把每个新的增量构件集成到现有软件体系结构中时,必须不破坏原来已经开发出的产品
    • 必须把软件的体系结构设计得便于按这种方式进行扩充,向现有产品中加入新构件的过程必须简单、方便,也就是说,软件体系结构必须是开放的。

1.4.4 螺旋模型

螺旋模型的基本思想是,使用原型及其他方法来尽量降低风险。理解这种模型的一个简便方法,是把它看作在每个阶段之前都增加了风险分析过程的快速原型模型。

1.4.5 喷泉模型

1.4.6 Rational统一过程(Rational Unified Process RUP)

最佳实践

  • 迭代式开发

    迭代式开发允许在每次迭代过程中需求都可以有变化,这种开发方法通过一系列细化来加深对问题的理解,因此能更容易地容纳需求的变更

  • 管理需求

    RUP描述了如何提取、组织系统的功能性需求和约束条件并把它们文档化

  • 使用基于架构的体系结构

    RUP提供了使用现有的或新开发的构件定义体系结构的系统化方法,从而有助于降低软件开发的复杂性,提高软件重用率

  • 可视化建模

    可视化建模语言UML紧密地联系在一起,在开发过程中建立起软件系统的可视化模型,可以帮助人们提高管理软件复杂性的能力

  • 验证软件质量

    软件质量评估不再是事后型的或由单独小组进行的孤立活动,而是内建在贯穿于整个开发过程的、由全体成员参与的所有活动中

  • 控制软件变更

    RUP描述了如何控制、跟踪和监控修改,以确保迭代开发的成功

1.4.7 敏捷过程与极限编程

二 可行性研究

2.1 可行性研究的任务

可行性研究的目的不是解决问题,而是确定问题是否值得去解决

至少从三个方面研究每种解法的可行性:

  • 技术可行性
  • 经济可行性
  • 操作可行性

2.2 可行性研究过程

可行性研究过程有如下步骤:

  • 复查系统规模和目标

    分析员访问关键人员,仔细阅读和分析有关的材料,以便对问题定义阶段书写的关于规模和目标的报告书进一步复查确认,改正含糊或不确切的叙述,清晰地描述对目标系统的一切限制和约束。这个步骤的工作,实质上是为了确保分析员正在解决的问题确实是要求他解决的问题。

  • 研究正在使用的系统

    现有的系统是信息的重要来源。显然,如果目前有一个系统正被人使用,那么这个系统必定能完成某些有用的工作,因此,新的目标系统必须也能完成它的基本功能;另一方面,如果现有的系统是完美无缺的,用户自然不会提出开发新系统的要求,因此,现有的系统必然有某些缺点,新系统必须能解决旧系统中存在的问题。

    应该仔细阅读分析现有系统的文档资料和使用手册,也要实地考察现有的系统。

    常见的错误做法是花费过多时间去分析现有的系统。

    没有一个系统是在“真空”中运行的,绝大多数系统都和其他系统有联系。

  • 导出新系统的高层逻辑模型

    优秀的设计过程通常是从现有的物理系统出发,导出现有系统的逻辑模型,再参考现有系统的逻辑模型,设想目标系统的逻辑模型,最后根据目标系统的逻辑模型建造新的物理系统。

  • 进一步定义问题

    可行性研究的前4个步骤实质上构成一个循环。分析员定义问题,分析这个问题,导出一个试探性的解;在此基础上再次定义问题,再一次分析这个问题,修改这个解;继续这个循环过程,直到提出的逻辑模型完全符合系统目标。

  • 导出和评价供选择的解法

    分析员应该从他建议的系统逻辑模型出发,导出若干个较高层次的物理解法供比较和选择。

    其次可以考虑操作方面的可行性。分析员应该根据使用部门处理事务的原则和习惯检查技术上可行的那些方案,去掉其中从操作方式或操作过程的角度看用户不能接受的方案。

    接下来应该考虑经济方面的可行性。分析员应该估计余下的每个可能的系统的开发成本和运行费用,并且估计相对于现有的系统而言这个系统可以节省的开支或可以增加的收入。

    最后为每个在技术、操作和经济等方面都可行的系统制定实现进度表,这个进度表不需要制定得很详细,通常只需要估计生命周期每个阶段的工作量。

  • 推荐行动方针

    根据可行性研究结果应该决定的一个关键性问题是:
    是否继续进行这项开发工程?分析员必须清楚地表明他对这个关键性决定的建议。如果分析员认为值得继续进行这项开发工程,那么他应该选择一种最好的解法,并且说明选择这个解决方案的理由。通常客户主要根据经济上是否划算决定是否投资于一项开发工程,因此分析员对于所推荐的系统必须进行比较仔细的成本/效益分析。

  • 草拟开发计划书

    分析员应该为所推荐的方案草拟一份开发计划,除了制定工程进度表之外还应该估计对各类开发人员和各种资源的需要情况,应该指明什么时候使用以及使用多长时间。此外还应该估计系统生命周期每个阶段的成本。最后应该给出下一个阶段(需求分析)的详细进度表和成本估计。

  • 写文档提交审查

    应该把上述可行性研究各个步骤的工作结果写成清晰的文档,请用户、客户组织的负责人及评审组审查,以决定是否继续这项工程及是否接受分析员推荐的方案。

2.3 系统流程图

系统流程图是概括地描绘物理系统的传统工具。

基本思想:用图形符号以黑盒子形式描绘组成系统的每个部件(程序、文档、数据库、人工过程等)。

系统流程图表达的是数据在系统各部件之间流动的情况,而不是对数据进行加工处理的控制过程,因此尽管系统流程图的某些符号和程序流程图的符号形式相同,但是它却是物理数据流图而不是程序流程图。

2.4 数据流图

数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。

2.5 数据字典

数据字典是关于数据的信息的集合,也就是对数据流图中包含的所有元素的定义的集合。

数据字典的用途:

  • 作为分析阶段的工具
  • 数据字典中包含的每个数据元素的控制信息是很有价值的
  • 是开发数据库的第一步

例如:

  • 名字:订货报表
  • 别名:订货信息
  • 描述:xxxxxx
  • 定义:订货报表=零件编号+零件名称+订货数量+目前价格+主要供应者+次要供应者
  • 位置:输出到打印机

2.6 成本/效益分析

三种估算技术:

  • 代码行技术
  • 任务分解技术
  • 自动估算成本技术

成本/效益分析方法主要从四个方面考虑:

  • 货币的时间价值
  • 投资回收期
  • 纯收入
  • 投资回收率

三 需求分析

需求分析是软件定义时期的最后一个阶段,它的基本任务是准确地回答“系统必须做什么”这个问题

3.1 需求分析的任务

3.1.1 确定对系统的综合要求

  • 功能需求

    指定系统必须提供的服务。通过需求分析应该划分出系统必须完成的所有功能。

  • 性能需求

    指定系统必须满足的定时约束或容量约束,通常包括响应时间、信息量速率、主存容量、磁盘容量、安全性等方面的需求。

  • 可靠性与可用性需求

  • 定量的指定系统的可靠性,可用性与可靠性密切相关,量化了用户可以使用吸引的程度。

  • 出错处理需求

    说明系统对环境错误应该怎样响应

  • 接口需求

    描述应用系统与它的环境通信的格式,常见的接口需求有:用户接口需求、硬件接口需求、软件接口需求、通信接口需求

  • 约束

    设计约束或实现约束描述在设计或实现应用系统时应该遵守的 限制条件,常见的约束有:精度、工具和语言约束、设计约束。

  • 逆向需求

    说明软件不应该做什么

  • 将来可能提出的要求

    明确列出哪些虽然不属于当前系统开发范畴,但是据分析将来很可能会提出来的要求。

3.1.2 分析系统的数据要求

复杂的数据由许多基本的数据元素组成,数据结构表示数据元素之间的逻辑关系。利用数据字典可以全面准确地定义数据,但是数据字典的缺点是不够形象直观。为了提高可理解性,常常利用图形工具辅助描绘数据结构。

3.1.3 导出系统的逻辑模型

综合上述两项分析的结果可以导出系统的详细的逻辑模型,通常用数据流图、实体联系图、状态转换图、数据字典和主要的处理算法描述这个逻辑模型。

3.1.4 修正系统开发计划

根据在分析过程中获得的对系统的更深入更具体的了解,可以比较准确地估计系统的成本和进度,修正以前制定的开发计划。

3.2 与用户沟通获取需求的方法

3.2.1 访谈

3.2.2 面向数据流自顶向下求精

结构化分析方法就是面向数据流自顶向下逐步求精进行需求分析的方法。通过可行性研究已经得出了目标系统的高层数据流图,需求分析的目标之一就是把数据流和数据存储定义到元素级。

为了达到这个目标,通常从数据流图的输出端着手分析,这是因为系统的基本功能是产生这些输出,输出数据决定了系统必须具有的最基本的组成元素。

数据流图是帮助复查的极好工具,从输入端开始,分析员借助数据流图、数据字典和IPO图向用户解释输入数据是怎样一步一步地转变成输出数据的。这些解释集中反映了通过前面的分析工作分析员所获得的对目标系统的认识。

3.2.3 简易的应用规格说明技术

简易的应用规格说明技术是为了解决使用传统的访谈或面向数据流自顶向下求精方法定义需求时,用户处于被动地位而且往往有意无意地与开发者区分“彼此”。由于不能像同一个团队的人那样齐心协力地识别和精化需求,这两种方法的效果有时并不理想的问题,提出的。

3.2.4 快速建立软件原型

快速原型就是快速建立起来的旨在演示目标系统主要功能的可运行的程序,具有快速和容易修改的特点。

  • 第四代技术
  • 可重用的软件构件
  • 形式化规格说明和原型环境

3.3 分析建模与规格说明

3.3.1分析建模

为了开发复杂的系统,应从不同角度(模型)抽象出目标系统的特性(数据模型、功能模型、行为模型)

  • 实体联系图,描述数据对象及数据对象之间的关系,是用于建立数据模型的图形
  • 数据流图是建立功能模型的基础
  • 状态转换图描绘了系统的各种行为和在不同状态间转换的方式

3.3.2 软件需求规格说明

软件需求规格说明是需求分析阶段得出的最主要的文档。

通常用自然语言完整、准确、具体地描述系统的数据要求、功能需求、性能需求、可靠性和可用性要求、出错处理需求、接口需求、约束、逆向需求以及将来可能提出的要求。

3.4 实体联系图

数据模型中包含三种相互关联的信息:数据对象、数据对象的属性及数据对象彼此间相互连接的关系

3.4.1 数据对象

数据对象是对软件必须理解的复合信息的抽象。

3.4.2 属性

属性定义了数据对象的性质。

3.4.3 联系

数据对象彼此之间相互连接的方式称为联系,也叫关系。

  • 一对一联系(1:1)
  • 一对多联系(1:N)
  • 多对多联系(M:N)

3.4.4 ER图

ER图中包含了实体(即数据对象)、关系和属性3种基本成分,通常用矩形框代表实体,用连接相关实体的菱形框表示关系,用椭圆形或圆角矩形表示实体(或关系)的属性,并用直线把实体(或关系)与其属性连接起来。

3.5数据规范化

范式

  • 第一范式
  • 第二范式
  • 第三范式

3.6 状态转换图

状态转换图(简称为状态图)通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。此外,状态图还指明了作为特定事件的结果系统将做哪些动作。

3.7 其他图形工具

3.7.1 层次方框图

3.7.2 Warnier图

3.7.3 IPO图

3.8 验证软件需求

3.8.1 从四个方面验证软件需求的正确性

  • 一致性,一致性所有需求必须是一致的,任何一条需求不能和其他需求互相矛盾。
  • 完整性,完整性需求必须是完整的,规格说明书应该包括用户需要的每一个功能或性能。
  • 现实性,现实性指定的需求应该是用现有的硬件技术和软件技术基本上可以实现的。
  • 有效性,有效性必须证明需求是正确有效的,确实能解决用户面对的问题。

3.8.2 验证软件需求的方法

  • 验证需求的一致性
  • 验证需求的现实性
  • 验证需求的完整性和有效性

3.8.3 用于需求分析的软件工具

四 形式化说明技术

4.1 概述

4.1.1 非形式化方法的缺点

用自然语言书写的系统规格说明书,可能存在矛盾、二义性、含糊性、不完整性及抽象层次混乱等问题。

4.1.2 形式化方法的优点

为了克服非形式化方法的缺点,人们把数学引入软件开发过程,创造了基于数学的形式化方法。

4.1.3 应用形式化方法的准则

  • 应该选用适当的表示方法
  • 应该形式化,但不要过分形式化
  • 应该估算成本
  • 应该有形式化顾问随时提供咨询
  • 不应该放弃传统的开发方法
  • 应该建立详尽的文档
  • 不应该放弃质量标准
  • 不应该盲目依赖性形式化方法
  • 应该测试、测试再测试
  • 应该重用

4.2 有穷状态机

4.3 Petri网

4.4 Z语言

五 总体设计

5.1 设计过程

典型的总体设计步骤:

  • 设想供选择的方案

    在总体设计阶段分析员应该考虑各种可能的实现方案,并且力求从中选出最佳方案。

    需求分析阶段得出的数据流图是总体设计的极好的出发点。

    设想供选择的方案的一种常用的方法是,设想把数据流图中的处理分组的各种可能的方法,抛弃在技术上行不通的分组方法(例如,组内不同处理的执行时间不相容),余下的分组方法代表可能的实现策略,并且可以启示供选择的物理系统。

  • 选取合理的方案

    应该从前一步得到的一系列供选择的方案中选取若干个合理的方案,通常至少选取低成本、中等成本和高成本的3种方案。在判断哪些方案合理时应该考虑在问题定义和可行性研究阶段确定的工程规模和目标,有时可能还需要进一步征求用户的意见。

    对每个合理的方案,分析员都应该准备下列4份资料。

    (1) 系统流程图。

    (2) 组成系统的物理元素清单。

    (3) 成本/效益分析。

    (4) 实现这个系统的进度计划。

  • 推荐最佳方案

    用户和有关的技术专家应该认真审查分析员所推荐的最佳系统,如果该系统确实符合用户的需要,并且是在现有条件下完全能够实现的,则应该提请使用部门负责人进一步审批。在使用部门的负责人也接受了分析员所推荐的方案之后,将进入总体设计过程的下一个重要阶段——结构设计。

  • 功能分解

    为了最终实现目标系统,必须设计出组成这个系统的所有程序和文件(或数据库)。对程序(特别是复杂的大型程序)的设计,通常分为两个阶段完成:首先进行结构设计,然后进行过程设计。

    为确定软件结构,首先需要从实现角度把复杂的功能进一步分解。分析员结合算法描述仔细分析数据流图中的每个处理,如果一个处理的功能过分复杂,必须把它的功能适当地分解成一系列比较简单的功能。

  • 设计软件结构

    通常程序中的一个模块完成一个适当的子功能。应该把模块组织成良好的层次系统,顶层模块调用它的下层模块以实现程序的完整功能,每个下层模块再调用更下层的模块,完成程序的一个子功能,最下层的模块完成最具体的功能。

  • 设计数据库

    对于需要使用数据库的那些应用系统,软件工程师应该在需求分析阶段所确定的系统数据需求的基础上,进一步设计数据库。

  • 制定测试计划

    在软件开发的早期阶段考虑测试问题,能促使软件设计人员在设计时注意提高软件的可测试性。

  • 书写文档

    应该用正式的文档记录总体设计的结果,在这个阶段应该完成的文档通常有下述几种。

    • 系统说明
    • 用户手册
    • 测试计划
    • 详细的实现计划
    • 数据库设计结果
  • 审查和复审

    最后应该对总体设计的结果进行严格的技术审查,在技术审查通过之后再由客户从管理角度进行复审。

5.2 设计原理

5.2.1 模块化

模块化就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求。

5.2.2 抽象

软件工程过程的每一步都是对软件解法的抽象层次的一次精化。在可行性研究阶段,软件作为系统的一个完整部件;在需求分析期间,软件解法是使用在问题环境内熟悉的方式描述的;当由总体设计向详细设计过渡时,抽象的程度也就随之减少了;最后,当源程序写出来以后,也就达到了抽象的最低层。

5.2.3 逐步求精

逐步求精定义为为了能集中精力解决主要问题而尽量推迟对问题细节的考虑。

5.2.4 信息隐藏和局部化

5.2.5 模块独立

模块的独立程度可以由两个定性标准度量,这两个标准分别称为内聚和耦合。

  • 耦合 尽量使用数据耦合,少用控制耦合和特征耦合,限制公共环境耦合的范围,完全不用内容耦合
    • 数据耦合,两个模块彼此间通过参数交换信息,而且交换的信息仅仅是数据,那么这种耦合称为数据耦合。数据耦合是低耦合。系统中至少必须存在这种耦合。
    • 控制耦合,传递的信息中有控制信息(尽管有时这种控制信息以数据的形式出现),则这种耦合称为控制耦合。控制耦合是中等程度的耦合。
    • 特征耦合,当把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合。
    • 公共环境耦合,当两个或多个模块通过一个公共数据环境相互作用时,它们之间的耦合称为公共环境耦合。
    • 内容耦合,应该坚决避免使用内容耦合
      • 一个模块访问另一个模块的内部数据
      • 一个模块不通过正常入口而转到另一个模块的内部
      • 两个模块有一部分程序代码重叠(只可能出现在汇编程序中)
      • 一个模块有多个入口(这意味着一个模块有几种功能)
  • 内聚
    • 低内聚
      • 一个模块完成一组任务,这些任务彼此间即使有关系,关系也是很松散的,就叫做偶然内聚。
      • 一个模块完成的任务在逻辑上属于相同或相似的一类,则称为逻辑内聚
      • 一个模块包含的任务必须在同一段时间内执行,就叫时间内聚。
    • 中内聚
      • 一个模块内的处理元素是相关的,而且必须以特定次序执行,则称为过程内聚。
      • 模块中所有元素都使用同一个输入数据和(或)产生同一个输出数据,则称为通信内聚。
    • 高内聚
      • 一个模块内的处理元素和同一个功能密切相关,而且这些处理必须顺序执行(通常一个处理元素的输出数据作为下一个处理元素的输入数据),则称为顺序内聚。
      • 模块内所有处理元素属于一个整体,完成一个单一的功能,则称为功能内聚。功能内聚是最高程度的内聚。

5.3 启发规则

  • 改进软件结构提高模块独立性
  • 模块规模应该适中
  • 深度、宽度、扇出和扇入都应该适当
  • 模块的作用域应该在控制域之内
  • 力争降低模块接口的复杂程度
  • 设计单入口单出口的模块
  • 模块功能应该可以预测

5.4 描绘软件结构的图形工具

5.4.1 层次图和HIPO图

5.4.2 结构图

5.5 面向数据流的设计方法

六 详细设计

6.1 结构程序设计

  • 顺序
  • 选择
  • 循环

6.2 人机界面设计

6.2.1 设计问题

  • 系统响应时间
  • 用户帮助设施
  • 出错信息处理
  • 命令交互

6.2.2 设计过程

6.2.3 人机界面设计指南

  • 一般交互指南
  • 信息显示指南
  • 数据输入指南

6.3 过程设计的工具

6.3.1 程序流程图(程序框图)

6.3.2 盒图

6.3.3 PAD图

6.3.4 判定表

6.3.5 判定树

6.3.6 过程设计语言PDL

6.4 面向数据结构的设计方法

6.4.1 Jackson图

6.4.2 改进的Jackson图

6.4.3 Jackson法

6.5 程序复杂度的定量度量

6.5.1 McCabe方法

  • 流图
  • 计算环形复杂度的方法
    • 流图中线性无关的区域数等于环形复杂度
    • 流图G的环形复杂度V(G)=E-N+2,其中,E是流图中边的条数,N是结点数
    • 流图G的环形复杂度V(G)=P+1,其中,P是流图中判定结点的数目

七 实现

7.1 编码

7.1.1 选择程序设计语言

7.1.2 编码风格

7.2 软件测试基础

7.2.1 软件测试的目标

7.2.2 软件测试准测

7.2.3 软件测试方法

  • 黑盒测试(功能测试)
  • 白盒测试(结构测试)

7.2.4 测试步骤

  • 模块测试(单元测试)
  • 子系统测试
  • 系统测试
  • 验收测试(确认测试)
  • 平行测试

7.3 单元测试

单元测试与编码属于同一阶段

单元测试主要使用白盒测试技术

7.3.1 测试重点:

  • 模块接口
  • 局部数据结构
  • 重要的执行通路
  • 出错处理通路
  • 边界条件(最重要)

7.3.2 代码审查

7.3.3 计算机测试

7.3 单元测试

7.4 集成测试

7.4.1 自顶向下集成

自顶向下集成方法是从主控制模块开始,沿着程序的控制层次向下移动,逐渐把各个模块结合起来。在把附属于(及最终附属于)主控制模块的那些模块组装到程序结构中去时,或者使用深度优先的策略,或者使用宽度优先的策略。

深度优先的结合方法先组装在软件结构的一条主控制通路上的所有模块。选择一条主控制通路取决于应用的特点,并且有很大任意性。

宽度优先的结合方法是沿软件结构水平地移动,把处于同一个控制层次上的所有模块组装起来。

7.4.2 自底向上集成

自底向上测试从“原子”模块(即在软件结构最低层的模块)开始组装和测试。因为是从底部向上结合模块,总能得到所需的下层模块处理功能,所以不需要存根程序。

7.4.3 不同集成测试策略的比较

  • 自顶向下测试方法主要优点是不需要测试驱动程序,能够在测试阶段的早期实现并验证系统的主要功能,而且能在早期发现上层模块的接口错误。
  • 自顶向下测试方法主要缺点是需要存根程序,可能遇到与此相联系的测试困难,低层关键模块中的错误发现较晚,而且用这种方法在早期不能充分展开人力。
  • 自底向上测试方法的优缺点与上述自顶向下测试方法的优缺点刚好相反。

7.4.4 回归测试

回归测试就是用于保证由于调试或其他原因引起的变化,不会导致非预期的软件行为或额外错误的测试活动。

7.5 确认测试

确认测试主要使用黑盒测试技术

确认测试也称为验收测试,它的目标是验证软件的有效性。

  • 验证指的是保证软件正确地实现了某个特定要求的一系列活动;
  • 确认指的是为了保证软件确实满足了用户需求而进行的一系列活动。

7.5.1 确认测试的范围

7.5.2 软件配置复查

7.5.3 Alpha和Beta测试

  • Alpha测试由用户在开发者的场所进行,受控
  • Beta测试实在开发者不能控制的环境“真实”应用

7.6 白盒测试技术

7.6.1 逻辑覆盖

  • 语句覆盖,使被测程序中每个语句至少执行一次
  • 判定覆盖(分支覆盖),不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该至少执行一次,也就是每个判定的每个分支都至少执行一次
  • 条件覆盖,不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取到各种可能的结果
  • 判定/条件覆盖,使得判定表达式中的每个条件都取到各种可能的值,而且每个判定表达式也都取到各种可能的结果
  • 条件组合覆盖,使得每个判定表达式中条件的各种可能组合都至少出现一次

7.6.2 控制结构测试

  • 基本路径测试
  • 条件测试
  • 循环测试

7.7 黑盒测试技术

7.7.1 等价划分

7.7.2 边界值分析

7.7.3 错误推测

7.8 调试

7.9 软件可靠性