第5章 总体设计

总体设计的基本目的就是回答“概括地说,系统应该如何实现”这个问题,因此,总体设计又称为 概要设计初步设计。 总体设计阶段的另一项重要任务是设计软件的结构,也就是要确定系统中每个程序是由哪些模块组成的,以及这些模块相互间的关系。

软件设计的任务(技术观点)

根据用信息域表示的软件需求,以及功能和性能需求,进行:

  • 数据设计:侧重于数据结构的定义

  • 系统结构设计:定义软件系统各主要成份之间的关系

  • 过程设计:是把结构成份转换成软件的过程性描述。在编码步骤,根据这种过程性描述,生成源程序代码,然后通过测试最终得到完整有效的软件

软件设计的任务(管理观点)

从工程管理的角度来看,软件设计分两步完成。

  • 概要设计:将软件需求转化为数据结构和软件的系统结构。(概要设计对应了技术观点中的系统结构设计)

  • 详细设计:即过程设计。通过对结构表示进行细化,得到软件的详细的数据结构和算法。(详细设计对应了技术观点中的数据设计和过程设计)

5.1 设计过程

总体设计步骤

1.制定规范

在进入软件开发阶段之初,首先应为软件开发组制定在设计时应该共同遵守的标准,以便协调组内各成员的工作。

  • 阅读和理解软件需求说明书,确认用户要求能否实现,明确实现的条件,从而确定设计的目标,以及它们的优先顺序

  • 根据目标确定最合适的设计方法

  • 规定设计文档的编制标准

  • 规定编码的信息形式,与硬件,操作系统的接口规约,命名规则等

2.软件系统结构的总体设计

基于功能层次结构建立系统

  • 采用某种设计方法,将系统按功能划分成模块的层次结构

  • 确定每个模块的功能

  • 建立与已确定的软件需求的对应关系

  • 确定模块间的调用关系

  • 确定模块间的接口

  • 评估模块划分的质量

3.处理方式设计

确定为实现系统的功能需求所必需的算法,评估算法的性能

  • 确定为满足系统的性能需求所必需的算法和模块间的控制方式

  • 周转时间

  • 响应时间

  • 吞吐量

  • 精度

  • 确定外部信号的接收发送形式

4.数据结构设计

  • 确定软件涉及的文件系统的结构以及数据库的模式、子模式,进行数据完整性和安全性的设计

  • 确定输入,输出文件的详细的数据结构结合算法设计,确定算法所必需的逻辑数据结构及其操作

    确定对逻辑数据结构所必需的那些操作的程序模块(软件包)

  • 限制和确定各个数据设计决策的影响范围

  • 若需要与操作系统或调度程序接口所必须的控制表等数据时,确定其详细的数据结构和使用规则

  • 数据的保护性设计:在软件设计中就插入自动检错,报错和纠错的功能

  • 一致性设计:保证软件运行过程中所使用的数据的类型和取值范围不变; 在并发处理过程中使用封锁和解除封锁机制保持数据不被破坏;

  • 冗余性设计:针对同一问题,由两个开发者采用不同的程序设计风格不同的算法设计软件,当两者运行结果之差不在允许范围内时,利用检错系统予以纠正,或使用表决技术决定一个正确结果。

5.可靠性设计

可靠性设计也叫做质量设计。在运行过程中,为了适应环境的变化和用户新的要求,需经常对软件进行改造和修正。在软件开发的一开始就要确定软件可靠性和其它质量指标,考虑相应措施,以使得软件易于修改和易于维护

概要设计文档

概要设计阶段完成时应编写以下文档:

  • 概要设计说明书

  • 数据库设计说明书

  • 用户手册

  • 制定初步的测试计划

概要设计的评审

  • 可追溯性:确认该设计是否复盖了所有已确定的软件需求,软件每一成份是否可追溯到某一项需求

  • 接口:确认该软件的内部接口与外部接口是否已经明确定义。模块是否满足高内聚和低耦合的要求。模块作用范围是否在其控制范围之内

  • 风险:确认该设计在现有技术条件下和预算范围内是否能按时实现

  • 实用性:确认该设计对于需求的解决方案是否实用

  • 技术清晰度:确认该设计是否以一种易于翻译成代码的形式表达

  • 可维护性:确认该设计是否考虑了方便未来的维护

  • 质量:确认该设计是否表现出良好的质量特征

  • 各种选择方案:看是否考虑过其它方案,比较各种选择方案的标准是什么

    限制:评估对该软件的限制是否现实,是否与需求一致

  • 其它具体问题:对于文档、可测试性、设计过程..等进行评估

5.2 设计原理

核心概念:

  • 软件结构;

  • 程序结构;

  • 模块化;

  • 信息隐蔽;

  • 模块的独立性;

  • 自顶向下,逐步细化;

  • 抽象化;

软件结构

软件的体系结构通过一个划分过程来完成。该划分过程从需求分析确立的目标系统的模型出发,对整个问题进行分割,使其每个部分用一个或几个软件成份加以解决,整个问题就解决了

注:软件结构包括两部分。程序的模块结构和数据的结构

程序结构

程序结构表明了程序各个部件(模块)的组织情况,是软件的过程表示。

5.2.1 模块化

模块 是由边界元素限定的相邻程序元素(例如,数据说明、可执行的语句)的序列,而且有一个总体标识符代表它。模块 是构成程序的基本构件。

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

软件系统的模块化是指整个软件被划分成若干单独命名和可编址的部分,称之为模块。这些模块可以被组装起来以满足整个问题的需求。

注:软件的复杂性并不是随着分解模块的增多而变的越来越容易,相反随着模块的增加由于交互的复杂,变的更加复杂。

模块定义

“模块”,又称“组件”。它一般具有如下三个基本属性:

  • 功能:描述该模块实现什么功能

  • 逻辑:描述模块内部怎么做

  • 状态:该模块使用时的环境和条件

在描述一个模块时,还必须按模块的 外部特性 内部特性 分别描述

  • 模块的外部特性: 模块的模块名、参数表、其中的输入参数和输出参数,以及给程序以至整个系统造成的影响

  • 模块的内部特性: 完成其功能的程序代码和仅供该模块内部使用的数据

模块化 是为了使一个复杂的大型程序能被人的智力所管理,是软件应该具备的唯一属性。

设函数C(x)定义问题x的复杂程度,函数E(x)确定解决问题x需要的工作量(时间)。对于两个问题P1和P2

  • 如果 C(P1)>C(P2)

  • 显然 E(P1)>E(P2)

根据人类解决一般问题的经验,另一个有趣的规律是 C(P1+P2)>C(P1)+C(P2)

也就是说,如果一个问题由P1和P2两个问题组合而成,那么它的复杂程度大于分别考虑每个问题时的复杂程度之和。

综上所述,得到下面的不等式 E(P1+P2)>E(P1)+E(P2)

这个不等式导致 “各个击破” 的结论——把复杂的问题分解成许多容易解决的小问题,原来的问题也就容易解决了。这就是模块化的根据。

如果无限地分割软件,最后为了开发软件而需要的工作量也就小得可以忽略了。事实上,还有另一个因素在起作用,从而使得上述结论不能成立。

当模块数目增加时每个模块的规模将减小,开发单个模块需要的成本(工作量)确实减少了;但是,随着模块数目增加,设计 模块间接口 所需要的工作量也将增加。根据这两个因素,得出了图中的总成本曲线。每个程序都相应地有一个 最适当的模块数目M,使得系统的开发成本最小。

虽然目前还不能精确地决定M的数值,但是在考虑模块化的时候总成本曲线确实是有用的指南。

采用模块化原理可以使软件结构清晰,不仅容易设计也容易阅读和理解。模块化也有助于软件开发工程的组织管理,一个复杂的大型程序可以由许多程序员分工编写不同的模块,并且可以进一步分配技术熟练的程序员编写困难的模块。

5.2.2 抽象

人类在认识复杂现象的过程中使用的最强有力的思维工具是 抽象。人们在实践中认识到,在现实世界中一定事物、状态或过程之间总存在着某些相似的方面(共性)。把这些相似的方面集中和概括起来,暂时忽略它们之间的差异,这就是抽象。或者说 抽象就是抽出事物的本质特性而暂时不考虑它们的细节。

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

5.2.3 逐步求精

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

逐步求精最初是由Niklaus Wirth提出的一种自顶向下的设计策略。按照这种设计策略,程序的体系结构是通过逐步精化处理过程的层次而设计出来的。通过逐步分解对功能的宏观陈述而开发出层次结构,直至最终得出用程序设计语言表达的程序。

  • 求精实际上是细化过程。

  • 抽象求精 是一对互补的概念。

自顶向下,逐步细化

将软件的体系结构按自顶向下方式,对各个层次的过程细节和数据细节逐层细化,直到用程序设计语言的语句能够实现为止,从而最后确立整个的体系结构。 逐步求精的主要目的是集中精力处理好当前急需处理的主要问题,而推迟对其它细节的处理

抽象概念与模块化和逐步求精是密切相关的,模块是一定抽象描述的体现,逐步求精一般只能够理解为一个过程,即是一个由顶向下的细化过程,而 抽象即可以理解为一个过程也可以理解为一种状态理解为过程时他表示从下向上的对于事物共性的抽取过程,而暂时忽略掉他们之间的差异抽象同时也可以理解为一种状态,表示一种使用问题环境语言描述的,较容易被人接受的描述体系。

5.2.4 信息隐藏和局部化

信息隐藏原理:应该这样设计和确定模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。

局部化 是指把一些关系密切的软件元素物理地放得彼此靠近。

如果在测试期间和以后的软件维护期间需要修改软件,使用信息隐藏原理作为模块化系统设计的标准就会带来极大好处。

信息隐蔽

由 parnas 方法提倡的信息隐蔽是指,每个模块的实现细节对于其它模块来说是隐蔽的。也就是说,模块中所包含的信息(包括数据和过程)不允许其它不需要这些信息的模块使用。

5.2.5 模块独立

模块的 独立性 很重要,因为

  1. 有效的模块化(即具有独立的模块)的软件比较容易开发出来。

  2. 独立的模块比较容易测试和维护。

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

模块的独立性

模块独立性, 是指软件系统中每个模块只涉及软件要求的具体的子功能, 而和软件系统中其它的模块的接口是简单的。

注:例如, 若一个模块只具有单一的功能且与其它模块没有太多的联系, 则称此模块具有模块独立性 一般采用两个准则度量模块独立性。即模块间耦合和模块内聚

耦合

是模块之间的互相连接的紧密程度的度量。

模块之间耦合的种类

  • 非直接耦合(Nondirect Coupling)

    • 如果两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的,这就是非直接耦合。这种耦合的模块独立性最强。\

  • 数据耦合 (Data Coupling)

    • 如果一个模块访问另一个模块时,彼此之间是通过简单数据参数 (不是控制参数、公共数据结构或外部变量) 来交换输入、输出信息的,则称这种耦合为数据耦合。

  • 标记耦合 (Stamp Coupling)

    • 如果一组模块通过参数表传递记录信息,就是标记耦合。这个记录是某一数据结构的子结构,而不是简单变量。

  • 控制耦合 (Control Coupling)

    • 如果一个模块通过传送开关、标志、名字等控制信息,明显地控制选择另一模块的功能,就是控制耦合。\

  • 外部耦合(External Coupling)

    • 一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。

  • 公共耦合(Common Coupling)

    • 若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合

  • 内容耦合 (Content Coupling)

    • 如果发生下列情形,两个模块之间就发生了内容耦合

      1. 一个模块直接访问另一个模块的内部数据;

      2. 一个模块不通过正常入口转到另一模块内部;

      3. 两个模块有一部分程序代码重迭(只可能出现在汇编语言中);

      4. 一个模块有多个入口。

内聚

标志一个模块内各个元素彼此结合的紧密程度。

模块内聚的种类

  • 功能内聚

    • 一个模块中各个部分都是完成某一具体功能必不可少的组成部分,或者说该模块中所有部分都是为了完成一项具体功能而协同工作,紧密联系,不可分割的。则称该模块为功能内聚模块。

  • 信息内聚

    • 这种模块完成多个功能,各个功能都在同一数据结构上操作,每一项功能有一个唯一的入口点。这个模块将根据不同的要求,确定该执行哪一个功能。由于这个模块的所有功能都是基于同一个数据结构(符号表),因此,它是一个信息内聚的模块。\

  • 通信内聚

    • 如果一个模块内各功能部分都使用了相同的输入数据,或产生了相同的输出数据,则称之为通信内聚模块。通常,通信内聚模块是通过数据流图来定义的。\

  • 过程内聚

    • 使用流程图做为工具设计程序时,把流程图中的某一部分划出组成模块,就得到过程内聚模块。例如,把流程图中的循环部分、判定部分、计算部分分成三个模块,这三个模块都是过程内聚模块。

  • 时间内聚

    • 时间内聚又称为经典内聚。这种模块大多为多功能模块,但模块的各个功能的执行与时间有关,通常要求所有功能必须在同一时间段内执行。例如初始化模块和终止模块。

  • 逻辑内聚

    • 这种模块把几种相关的功能组合在一起,每次被调用时,由传送给模块的判定参数来确定该模块应执行哪一种功能。

  • 巧合内聚

    • 巧合内聚又称为偶然内聚。当模块内各部分之间没有联系,或者即使有联系,这种联系也很松散,则称这种模块为巧合内聚模块,它是内聚程度最低的模块。

耦合和内聚的概念是Constantine,Yourdon,Myers和Stevens等人提出来的。上述 7 种内聚的优劣评分,将得到如下结果:

事实上,没有必要精确确定内聚的级别。重要的是设计时高内聚,并且能够辨认出低内聚的模块,有能力通过修改设计提高模块的内聚程度并且降低模块间的耦合程度,从而获得较高的模块独立性。

5.3 启发规则

模块设计的启发式规则一

模块功能的完善化

一个完整的模块应当有以下几部分:

  1. 执行规定的功能的部分;

  2. 出错处理的部分。当模块不能完成规定的功能时,必须回送出错标志,出现例外情况的原因。

  3. 如果需要返回一系列数据给它的调用者,在完成数据加工或结束时,应当给它的调用者返回一个结束状态标志。

消除重复功能,改善软件结构

  1. 完全相似:在结构上完全相似,可能只是在数据类型上不一致。此时可以采取完全合并的方法。

  2. 局部相似:找出其相同部分,分离出去,重新定义成一个独立的下一层模块。还可以与它的上级模块合并。

模块的作用域应该在控制域之内

作用域:受该模块内一个判定影响的所有模块的集合。

控制域:模块本身以及所有直接或间接从属于它的模块的集合。

在一个设计得很好的系统中,所有受判定影响的模块应该都从属于做出判定的那个模块,最好局限于做出判定的那个模块及它的直属下级模块

怎样修改软件结构才能使作用域是控制域的子集呢?

  • 方法1是把做判定的点往上移(例如,把判定从模块A中移到模块M中)

  • 方法2是把那些在作用域内但不在控制域内的模块移到控制域内(例如,把模块G移到模块A的下面,成为它的直属下级模块)。

模块设计的启发式规则二

模块的作用范围应在控制范围之内

模块的控制范围包括它本身及其所有的从属模块。

模块的作用范围是指模块内一个判定的作用范围,凡是受这个判定影响的所有模块都属于这个判定的作用范围。

如果一个判定的作用范围包含在这个判定所在模块的控制范围之内,则这种结构是简单的,否则,它的结构是不简单的。

尽可能减少高扇出结构,随着深度增大扇入

如果一个模块的扇出数过大,就意味着该模块过分复杂,需要协调和控制过多的下属模块。应当适当增加中间层次的控制模块。

模块设计的启发式规则三

避免或减少使用病态联接

模块的大小要适中

模块的大小,可以用模块中所含语句的数量的多少来衡量。把模块的大小限制在一定的范围之内。通常规定其语句行数在50~100左右,保持在一页纸之内,最多不超过500行。

模块设计的启发式规则四

设计功能可预测的模块,但要避免过分受限制的模块

一个功能可预测的模块,不论内部处理细节如何,但对相同的输入数据,总能产生同样的结果。但是,如果模块内部蕴藏有一些特殊的鲜为人知的功能时,这个模块就可能是不可预测的。对于这种模块,如果调用者不小心使用,其结果将不可预测。所谓过分限制是指由于对于局部数据结构进行了过分的要求,是模块的功能过分局限,降低了模块的灵活性。

软件包应满足设计约束和可移植性

为了使得软件包可以在某些特定的环境下能够安装和运行,对软件包提出了一些设计约束和可移植的要求。例如,设计约束有时要求一个程序段在存储器中覆盖自身。当这种情况出现时,设计出来的软件程序结构不得不根据重复程度、访问频率、调用间隔等等特性,重新加以组织。

力争降低模块接口的复杂程度

模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接口,使得信息传递简单并且和模块的功能一致。

  • 如:QUAD_ROOT(TBL,X)

求一元二次方程的根的模块,其中用数组TBL传送方程的系数,用数组X回送求得的根。

  • 使用接口可能是比较简单,如:\

    QUAD_ROOT(A,B,C,ROOT1,ROOT2)

其中A、B、C是方程的系数,ROOT1和ROOT2是算出的两个根。

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

5.4.1 层次图和HIPO图

层次图 用来描绘软件的层次结构。数据结构的层次方框图相同,但是表现的内容却完全不同。层次图很适于在 自顶向下 设计软件的过程中使用。

HIPO图 是美国IBM公司发明的“层次图加输入/处理/输出图”的英文缩写。为了能使HIPO图具有可追踪性,在H图(层次图)里除了最顶层的方框之外,每个方框都加了编号。

5.4.2 结构图

Yourdon提出的 结构图 是进行软件结构设计的工具。图中一个方框代表一个模块,框内注明模块的名字或主要功能;方框之间的箭头(或直线)表示模块的调用关系。尾部是空心圆表示传递的是数据,实心圆表示传递的是控制信息。

一些附加的符号,可以表示模块的选择调用或循环调用。左图表示当模块M中某个判定为真时调用模块A,为假时调用模块B。右图表示模块M循环调用模块A、B和C。

5.5 面向数据流的设计方法

  1. 首先研究、分析和审查数据流图。从软件的需求规格说明中弄清数据流加工的过程,对于发现的问题及时解决。

  2. 然后根据数据流图决定问题的类型。数据处理问题典型的类型有两种:变换型和事务型。针对两种不同的类型分别进行分析处理。

  3. 由数据流图推导出系统的初始结构图。

  4. 利用一些启发式原则来改进系统的初始结构图,直到得到符合要求的结构图为止。

  5. 修改和补充数据词典。

  6. 制定测试计划。

5.5.1 概念

面向数据流的设计方法把信息流映射成软件结构,信息流的类型决定了映射的方法。信息流有下述两种类型。

1)变换流

信息沿输入通路进入系统,由外部形式变换成内部形式,进入系统的信息通过变换中心,经加工处理以后再沿输出通路变换成外部形式离开软件系统。当数据流图具有这些特征时,这种信息流就叫作变换流。

2)事务流

数据沿输入通路到达一个处理T,这个处理根据输入数据的类型在若干个动作序列中选出一个来执行。这类数据流应该划为一类特殊的数据流,称为事务流。

图中的处理T称为事务中心,它完成下述任务。

  1. 接收输入数据(输入数据又称为事务)。

  2. 分析每个事务以确定它的类型。

  3. 根据事务类型选取一条活动通路。

3)设计过程

结构图

结构图反映程序中模块之间的层次调用关系和联系,它以特定的符号表示模块、模块间的调用关系和模块间信息的传递。

软件的系统结构图

结构图中的模块类型

  • 变换型结构图

    1. 变换型数据处理问题的工作过程大致分为三步,即取得数据,变换数据和给出数据。

    2. 相应于取得数据、变换数据、给出数据,变换型系统结构图由输入、中心变换和输出等三部分组成。\

  • 事物型结构图

    1. 它接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。

    2. 在事务型系统结构图中,事务中心模块按所接受的事务的类型,选择某一事务处理模块执行。各事务处理模块并列。每个事务处理模块可能要调用若干个操作模块,而操作模块又可能调用若干个细节模块。\

变换分析

  1. 重画数据流图;

  2. 区分有效(逻辑)输入、有效(逻辑)输出和中心变换部分;

  3. 进行一级分解,设计上层模块;

  4. 进行二级分解,设计输入、输出和中心变换部分的中、下层模块;

变换原则

  1. 在选择模块设计的次序时,必须对一个模块的全部直接下属模块都设计完成之后,才能转向另一个模块的下层模块的设计。

  2. 在设计下层模块时,应考虑模块的耦合和内聚问题,以提高初始结构图的质量。

  3. 使用“黑箱”技术: 在设计当前模块时,先把这个模块的所有下层模块定义成“黑箱”,在设计中利用它们时,暂时不考虑其内部结构和实现。在这一步定义好的“黑箱”,在下一步就可以对它们进行设计和加工。这样,又会导致更多的“黑箱”。最后,全部“黑箱”的内容和结构应完全被确定。

  4. 在模块划分时,一个模块的直接下属模块一般在5个左右。如果直接下属模块超过10个,可设立中间层次。

  5. 如果出现了以下情况,就停止模块的功能分解:

  6. 当模块不能再细分为明显的子任务时;

  7. 当分解成用户提供的模块或程序库的子程序时;

  8. 当模块的界面是输入/输出设备传送的信息时;

  9. 当模块不宜再分解得过小时。

变换分析实例

事务分析

  1. 在很多软件应用中,存在某种作业数据流,它可以引发一个或多个处理,这些处理能够完成该作业要求的功能。这种数据流就叫做事务。

  2. 与变换分析一样,事务分析也是从分析数据流图开始,自顶向下,逐步分解,建立系统到结构图。

事物分析过程

  1. 识别事务源\

    利用数据流图和数据词典,从问题定义和需求分析的结果中,找出各种需要处理的事务。通常,事务来自物理输入装置。有时,设计人员还必须区别系统的输入、中心加工和输出中产生的事务。

  2. 规定适当的事务型结构\

    在确定了该数据流图具有事务型特征之后,根据模块划分理论,建立适当的事务型结构。

  3. 识别各种事务和它们定义的操作\

    从问题定义和需求分析中找出的事务及其操作所必需的全部信息,对于系统内部产生的事务,必须仔细地定义它们的操作

  4. 注意利用公用模块\

    在事务分析的过程中,如果不同事务的一些中间模块可由具有类似的语法和语义的若干个低层模块组成,则可以把这些低层模块构造成公用模块。

  5. 对每一事务,或对联系密切的一组事务,建立一个事务处理模块;

    如果发现在系统中有类似的事务,可以把它们组成一个事务处理模块。

  6. 对事务处理模块规定它们全部的下层操作模块

  7. 对操作模块规定它们的全部细节模块

变换分析和事物分析关系

变换分析是软件系统结构设计的主要方法。一般,一个大型的软件系统是变换型结构和事务型结构的混合结构。所以,我们通常利用以变换分析为主,事务分析为辅的方式进行软件结构设计。

分析实例

5.5.2 变换分析

变换分析 是一系列设计步骤的总称,经过这些步骤把具有变换流特点的 数据流图 按预先确定的模式 映射成软件结构

  • 例子 :汽车数字仪表板的设计

假设的仪表板将完成下述功能。

  1. 通过模数转换实现传感器和微处理机接口。

  2. 在发光二极管面板上显示数据。

  3. 指示每小时英里数mph,行驶的里程每加仑油行驶的英里数mpg等。

  4. 指示加速或减速。

  5. 超速警告:如果车速超过55英里/小时,则发出超速警告铃声。 在软件需求分析阶段应该对上述每条要求以及系统的其他特点进行全面的分析评价,建立必要的文档资料,特别是 数据流图

  6. 设计步骤

第1步复查基本系统模型。

第2步复查并精化数据流图。

假设在需求分析阶段产生的数字仪表板系统的数据流图如图所示。

第3步确定数据流图具有变换特性还是事务特性。

第4步确定输入流和输出流的边界,从而孤立出变换中心。

第5步完成“第一级分解”

软件结构代表对控制的自顶向下的分配,所谓分解就是分配控制的过程。对于变换流的情况,数据流图被映射成一个特殊的软件结构,这个结构控制输入、变换和输出等信息处理过程。

位于软件结构最顶层的控制模块Cm协调下述从属的控制功能。

  • 输入信息处理控制模块Ca,协调对 所有输入数据的接收

  • 变换中心控制模块Ct,管理对内部形式的数据的 所有操作

  • 输出信息处理控制模块Ce,协调 输出信息 的产生过程。

图中说明了第一级分解的方法。

对于数字仪表板的例子,第一级分解得出的结构如图所示。每个控制模块的名字表明了为它所控制的那些模块的功能。

第6步完成“第二级分解”

第二级分解就是 把数据流图中的每个处理映射成软件结构中一个适当的模块。

完成第二级分解的方法是,从变换中心的边界开始逆着输入通路向外移动,把输入通路中每个处理映射成软件结构中Ca控制下的一个低层模块;然后沿输出通路向外移动,把输出通路中每个处理映射成直接或间接受模块Ce控制的一个低层模块;最后把变换中心内的每个处理映射成受Ct控制的一个模块。

图表示进行第二级分解的普遍途径。

应该根据实际情况以及“好”设计的标准,进行实际的第二级分解。

对于数字仪表板系统的例子,第二级分解的结果分别用下面两个图和下一张的图描绘

为每个模块写一个简要说明,描述以下内容

  • 进出该模块的信息(接口描述)。

  • 模块内部的信息。

  • 过程陈述,包括主要判定点及任务等。

  • 对约束和特殊特点的简短讨论。

第7步使用 设计度量启发式规则 对第一次分割得到的软件结构进一步精化。

5.5.3 事务分析

数据流具有明显的事务特点时采用事务分析方法。 事务分析的设计步骤和变换分析的设计步骤大部分相同或类似,主要差别仅在于由数据流图到软件结构的映射方法不同。由事务流映射成的软件结构包括一个 接收分支 和一个 发送分支

5.5.4 设计优化

设计人员应该致力于开发能够满足所有 功能性能 要求,而且按照 设计原理启发式设计规则 衡量是值得接收的软件。

设计的早期阶段尽量对软件结构进行精化。

对时间起决定性作用的软件进行优化是合理的。

  1. 在不考虑时间因素的前提下开发并 精化软件结构

  2. 在详细设计阶段选出 最耗费时间 的那些模块,仔细地设计它们的处理过程(算法),以求提高效率。

  3. 使用高级程序设计语言编写程序。

  4. 在软件中孤立出那些大量占用处理机资源的模块。

  5. 必要时重新设计或用依赖于机器的语言重写上述大量占用资源的模块的代码,以求提高效率。

本章小结

  1. 总体设计阶段主要由 系统设计结构设计 两阶段组成。

  2. 进行软件结构设计时应该遵循的最主要的原理是 模块独立原理

  3. 在软件开发过程中既要充分重视和利用这些 启发式规则,又要从实际情况出发避免生搬硬套。

  4. 层次图结构图 是描绘软件结构的常用工具。

  5. 用形式化的方法由 数据流图映射出软件结构

习题

习题5.3.1

  • 为方便储户,某银行拟开发 计算机储蓄系统储户 填写的 存款单或取款单业务员 输入系统,

  • 如果是 存款,系统记录 存款人姓名、住址、存款类型、存款日期、利率 等信息,并印出存款单给储户;

  • 如果是 取款,系统计算 利息并印出利息清单 给储户。

2层,数据流

软件结构

习题5.3.2

  • 为方便旅客,某航空公司拟开发一个 机票预订系统

  • 旅行社把预订机票的 旅客信息(姓名、性别、工作单位、身份证号码、旅行时间、旅行目的地等) 输入 该系统,系统为 旅客 安排 航班印出 取票通知和账单,旅客在飞机起飞的前一天凭取票通知和账单 交款 取票,系统 校对 无误即 取出 机票 给旅客。

2层,数据流

软件结构

习题5.3.3

  • 目前住院病人主要由护士护理,这样做不仅需要大量护士,而且由于不能随时观察危重病人变化,还可能会延误抢救时机。某医院打算开发一个以计算机为中心的患者监护系统,试写出问题定义,并且分析开发该系统的可行性。

  • 医院对 患者 监护系统的基本要求是随时 接收,每个病人的 生理信号(脉搏、体温、血压、心电图等)定时记录 病人情况以形成 患者日志,当某个病人的生理信号超出医生规定的 安全范围 时,向值班护士发出 警告信息,此外,护士在需要时,还可以要求系统印出某个指定病人的 病情报告

2层,数据流图

软件体系

习题5.4

  • 美国某大学共有200名教师,校方与教师工会刚刚签订一项协议。按照协议,所有年工资超过$26000(含$26000)的教师工资保持不变,年工资少于$26000的教师将增加工资,所增加的工资数按下述方法计算:给每个由此教师所赡养的人(包括教师本人)每年补助$100,此外教师有一年工龄每年再多补助$50,但是,增加后的年工资总额不能多于$26000

  • 教师的工资档案存在行政办公室的光盘上,档案中有目前的年工资、赡养的人数、雇佣日期等信息。需要写一个程序计算并印出每名教师的原有工资和调整后的新工资

需求分析

要求:

  • (1)画出此系统的数据流图

  • (2)写出需求说明

  • (3)设计上述的工资调用程序(要求用HIPO图描述设计结果),设计时分别采用下述两种算法,并比较2种算法的优缺点

    • (a)搜索工资档案数据,找出年工资少于26000的人,计算新工资,校核是否超过26000,存储新工资,印出新旧工资对照表

    • (b)把工资档案数据按工资从最低到最高的次序排序,当工资数额超过26000时,即停止排序,计算新工资,校核是否超过限额,存储新工资,印出结果

  • (4)所画出的数据流图适用于哪种算法。

需求分析:

功能描述:

  1. 所有年工资超过$26000(含$26000)的教师工资保持不变。

  2. 年工资少于$26000的教师将增加工资,给每个由此教师所赡养的人(包括教师本人)每年补助$100,此外教师有一年工龄每年再多补助$50

    数据描述:工资表,教师档案表

0层

1层

2层

  • 排序需要遍历一遍以上的员工记录排序算法较为复杂

  • 检索算法,需要遍历一遍员工记录检索算法简单,有效

Last updated