文章目录
总体分析总括
总体设计的基本目的:系统应该如何实现?
总体设计=概要设计=初步设计
总体设计的任务:
- 划分出组成系统的物理元素:程序,文件,数据库,人工过程和文档。
- 设计软件的结构,确定系统每个程序都是由哪些模块组成的,以及这些模块相互间的关系。
总体设计过程:
5.1 设计过程
系统设计阶段:确定系统的具体实现方案
1. 设想供选择的方案
需求分析得到的数据流图是总体设计的极好的出发点。
2. 选取合理的方案
通常至少选择低成本、中等成本和高成本的3种方案。
对于每一个合理的方案,分析员应该准备下列4份资料:
- 系统流程图
- 组成系统的物理元素清单
- 成本效益分析
- 实现这个系统的进度计划
3. 推荐最佳方案
推荐一个最佳方案,并且制定详细的实现计划。
用户和有关专家认真审查分析员推荐的最佳系统,满足后,进入结构设计。
结构设计阶段:确定软件结构
4. 功能分解
结构设计(总体设计阶段任务)
结构设计:确定程序由哪些模块组成,以及这些模块之间的关系。
过程设计(详细设计阶段任务)
过程设计:确定每个模块的处理过程。
功能分析
为确定软件结构,需要从实现角度对复杂的功能进一步分解。
5. 设计软件结构
- 一个模块完成一个适当的子功能模块组织成良好的层次系统,顶层模块调用下层模块以实现程序的完整功能。每个下层模块调用更下层模块完成程序的子功能,最下层的模块完成最具体的任务。
- 如果数据流图已经细化到适当的层次,则可以直接从数据流图映射出软件结构。
6. 设计数据库
对于需要使用数据库的那些系统,软件工程师应该在需求分析阶段所确定系统需求的基础上进一步设计数据库。
7. 指定测试计划
8. 书写文档
系统说明
- 系统流程图描绘的系统构成方案
- 组成系统的物理元素清单
- 成本/效益分析
- 对最佳方案的概括描述
- 精化的数据流图
- 层次图或结构图描绘的软件结构
- IPO图或其他工具描绘各个模块的算法
- 模块间的接口关系
- 需求、功能和模块三者之间的交叉参照关系
1-4 选取合理方案后,每个方案的具备条件
用户说明
测试计划
详细的实现计划
数据库设计结果
9. 审查和复审
技术审查–>管理复审
5.2 设计原理
软件设计过程中应该遵循的基本原理和相关概念。
5.2.1 模块化
**模块:**是由边界元素限定的相邻程序元素的序列,而且有一个总体标识符代表它。
**模块化:**就是把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,把这些模块集成起来构成一个整体,可以完成指定的功能满足用户的需求。
为什么要模块化?
答:
- 模块化是为了使一个复杂的大型程序能被人的智力所管理,软件应该具备的惟一属性。
- 如果一个大型程序仅由一个模块组成,它将很难被人所理解。
同时考虑模块-接口问题
模块化的作用:
- 使软件结构清晰,不仅容易设计也容易阅读和理解。
- 模块化使软件容易测试和调试,因而有助于提高软件的可靠性。
- 模块化能够提高软件的可修改性。
- 模块化也有助于软件开发工程的组织管理。
5.2.2 抽象
**抽象:**现实世界中一定事物、状态或过程之间总存在着某些相似的方面(共性)。把这些相似的方面集中和概括起来,暂时忽略它们之间的差异,这就是抽象。
抽象就是抽出事物本质特性而暂时不考虑细节。
一般抽象过程:
5.2.3 逐步求精
**逐步求精:**为了能集中精力解决主要问题而尽量推迟对问题细节的考虑。逐步求精是人类解决复杂问题时采用的基本方法,也是许多软件工程技术的基础。
作用:
- 它能帮助软件工程师把精力集中在与当前开发阶段最相关的那些方面上,而忽略那些对整体解决方案来说虽然是必要的,然而目前还不需要考虑的细节。
- 逐步求精方法确保每个问题都将被解决,而且每个问题都将在适当的时候被解决,但是,在任何时候一个人都不需要同时处理7个以上知识块。
5.2.4 信息隐藏和局部化
**信息隐藏:**应该这样设计和确定模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。
**信息隐藏:**局部化的概念和信息隐藏概念是密切相关的。所谓局部化是指把一些关系密切的软件元素物理地放得彼此靠近。显然,局部化有助于实现信息隐藏。
5.2.5 模块独立
**模块独立:**模块独立的概念是模块化、抽象、信息隐藏和局部化概念的直接结果。希望这样设计软件结构,使得每个模块完成一个相对独立的特定子功能,并且和其他模块之间的关系很简单。
模块独立的重要性:
- 有效的模块化(即具有独立的模块)的软件比较容易开发出来。这是由于能够分割功能而且接口可以简化,当许多人分工合作开发同一个软件时,这个优点尤其重要。
- 独立的模块比较容易测试和维护。这是因为相对说来,修改设计和程序需要的工作量比较小,错误传播范围小,需要扩充功能时能够“插入”模块。
耦合和内聚
模块独立程度的两个定性标准度量:
耦合衡量不同模块彼此间互相依赖(连接)的紧密程度。
耦合要低,即每个模块和其他模块之间的关系要简单;
内聚衡量一个模块内部各个元素彼此结合的紧密程度。
内聚要高,每个模块完成一个相对独立的特定子功能。
模块因素 | 概念 | 要求 | 影响 |
---|---|---|---|
耦合 | 是对一个软件结构内不同模块之间互连程度的度量 | 在软件设计中应该追求尽可能松散耦合的系统 | 模块间的耦合程度强烈影响系统的可理解性、可测试性、可靠性和可维护性 |
内聚 | 标志一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展 | 1.设计时应该力求做到高内聚;2.中等程度的内聚也是可以采用的(效果同高内聚);3.低内聚不要使用。 | 内聚和耦合是密切相关的,模块内的高内聚往往意味着模块间的松耦合。实践表明内聚更重要,应该把更多注意力集中到提高模块的内聚程度上。 |
耦合
聚合类型 | 解释 |
---|---|
非直接耦合/完全独立 | 如果两个模块中的每一个都能独立地工作而不需要另一个模块的存在,那么它们完全独立。 |
数据耦合 | 如果两个模块彼此间通过参数交换信息,而且交换的信息仅仅是数据,那么这种耦合称为数据耦合 |
控制耦合 | 如果两个模块彼此间传递的信息中有控制信息,这种耦合称为控制耦合 |
特征耦合 | 当把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合 |
公共环境耦合 | 当两个或多个模块通过一个公共数据环境相互作用时,它们之间的耦合称为公共环境耦合。公共环境可以是全程变量、共享的通信区、内存的公共覆盖区、任何存储介质上的文件、物理设备等等 |
内容耦合 | 最高程度的耦合是内容耦合。如果出现下列情况之一,两个模块间就发生了内容耦合 |
附:
采取原则:
- 尽量使用数据耦合,
- 少用控制耦合和特征耦合,
- 限制公共环境耦合的范围,
- 完全不用内容耦合。
内聚
内聚 | 解释 |
---|---|
偶然内聚—低内聚 | 如果一个模块完成一组任务,这些任务彼此间即使有关系,关系也是很松散的,就称为偶然内聚 |
逻辑内聚—低内聚 | 如果一个模块完成的任务在逻辑上属于相同或相似的一类,则称为逻辑内聚 |
时间内聚—低内聚 | 如果一个模块包含的任务必须在同一段时间内执行,就称为时间内聚 |
过程内聚 | 如果一个模块内的处理元素是相关的,而且必须以特定次序执行,则称为过程内聚 |
通信内聚 | 如果模块中所有元素都使用同一个输入数据和(或)产生同一个输出数据,则称为通信内聚。即在同一个数据结构上操作 |
顺序内聚 | 如果一个模块内的处理元素和同一个功能密切相关,而且这些处理必须顺序执行,则称为顺序内聚 |
功能内聚 | 如果模块内所有处理元素属于一个整体,完成一个单一的功能,则称为功能内聚。功能内聚是最高程度的内聚 |
5.3 启发规则
1. 改进软件结构提高模块独立性
通过模块分解或合并,降低耦合提高内聚。两个方面:
➢模块功能完善化。一个完整的模块包含:
执行规定的功能的部分
出错处理的部分
返回一个“结束标志”
➢消除重复功能,改善软件结构。
完全相似
局部相似
2. 模块规模应该适中
➢ 经验表明,一个模块的规模不应过大,最好能写在一页纸内。通常规定50~100
行语句,最多不超过500行。数字只能作为参考,根本问题是要保证模块的独立性。
➢ 过大的模块往往是由于分解不充分,但是进一步分解必须符合问题结构,一般
说来,分解后不应该降低模块独立性。
➢ 过小的模块开销大于有效操作,而且模块数目过多将使系统接口复杂。
3. 深度,宽度,扇入,扇出都应适当
• 深度:软件结构中控制的层数,它往往能粗略地标志一个系统的大小和复杂程度。
• 宽度:软件结构内同一个层次上的模块总数的最大值。
• 扇出:一个模块直接控制(调用)的模块数目。
• 扇入:有多少个上级模块直接调用它。
4. 模块的作用域应该在控制域之内
• 模块的作用域:定义为受该模块内一个判定影响的所有模块的集合。
• 模块的控制域:是这个模块本身以及所有直接或间接从属于它的模块的集合。
• 在一个设计得很好的系统中,所有受判定影响的模块应该都从属于做出判定的那个模块,最好局限于做出判定的那个模块本身及它的直属下级模块。
5. 力争降低模块接口的复杂程度
• 模块接口复杂是软件发生错误的一个主要原因。应该仔细设计模块接
口,使得信息传递简单并且和模块的功能一致。
6. 设计单入口单出口的模块
➢ 警告软件工程师不要使模块间出现内容耦合。当从顶部进入模块并且
从底部退出来时,软件是比较容易理解的,因此也是比较容易维护的。
7. 模块功能应该可以预测
➢ 模块的功能应该能够预测,但也要防止模块功能过分局限。
➢ 功能可预测:如果一个模块可以当做一个黑盒子,只要输入的数据相
同就产生同样的输出,这个模块的功能就是可以预测的。
7. 模块功能应该可以预测
5.4 描绘软件结构的图形工具
5.4.1 层次图和HIPO图
层次图
HIPO图
5.4.2 结构图
层次图和结构图总结
5.5 面向数据流的设计方法
- 面向数据流的设计方法定义了一些不同的“映射”,利用这些映射可以把数据流图变换成软件结构。
- 因为任何软件系统都可以用数据流图表示,所以面向数据流的设计方法理论上可以设计任何软件的结构。通常所说的结构化设计方法(简称SD方法),也就是基于数据流的设计方法。
5.5.1 概念
1.变换流
2. 事务流
3. 设计过程
5.5.2 变换分析
1. 设计步骤
(1) 复查基本系统模型
• 确保系统的输入数据和输出数据符合实际。
(2) 复查并精化数据流图
• 对需求分析阶段得出的数据流图认真复查,并且在必要时进行精化。
• 不仅要确保数据流图给出了目标系统的正确的逻辑模型,而且应该使数据
流图中每个处理都代表一个规模适中相对独立的子功能。
(3) 确定数据流图具有变换特性还是事务特性
• 一个系统中的所有信息流都可以认为是变换流,但是,当遇到有明显事
务特性的信息流时,建议采用事务分析方法进行设计。确定数据流的全
局特性和局部特性。
(4) 确定输入流和输出流的边界,从而孤立出变换中心
• 输入流和输出流的边界和对它们的解释有关,不同设计人员可能会在流
内选取稍微不同的点作为边界的位置。
(5) 完成“第一级分解”。
• 位于软件结构最顶层的控制模块Cm协调下述从属的控制功能:
• 输入信息处理控制模块Ca,协调对所有输入数据的接收;
• 变换中心控制模块Ct,管理对内部形式的数据的所有操作;
• 输出信息处理控制模块Ce,协调输出信息的产生过程。
(6) 完成“第二级分解”
• 处理映射成软件结构中一个适当的模块。完成第二级分解的方
法是:
• 从变换中心的边界开始逆着输入通路向外移动,把输入通路中每个处理
映射成软件结构中Ca控制下的一个低层模块;
• 然后沿输出通路向外移动,把输出通路中每个处理映射成直接或间接受
模块Ce控制的一个低层模块;
• 最后把变换中心内的每个处理映射成受Ct控制的一个模块。
(7) 使用设计度量和启发式规则对第一次分割得到的软件结构进一步精化
• 为了产生合理的分解,得到尽可能高的内聚、尽可能松散的耦
合,为了得到一个易于实现、易于测试和易于维护的软件结构,
应该对初步分割得到的模块进行再分解或合并。
5.5.3 事务分析
5.5.4 设计优化
• 设计优化应该力求做到在有效的模块化的前提下使用最少量的模块,以及在能够满足信息要求的
前提下使用最简单的数据结构。
• 对于时间是决定性因素的应用场合,可能有必要在详细设计阶段,也可能在编写程序的过程中进
行优化。
• 软件开发人员应该认识到,程序中相对说比较小的部分(典型地,10%~20%),通常占用全部处理
时间的大部分(50%~80%)。对时间起决定性作用的软件进行优化:
• 在不考虑时间因素的前提下开发并精化软件结构;
• 在详细设计阶段选出最耗费时间的那些模块,仔
细地设计它们的处理过程,以求提高效率;
• 使用高级程序设计语言编写程序;
• 在软件中孤立出那些大量占用处理机资源的模块;
• 必要时重新设计或用依赖于机器的语言重写上述
大量占用资源的模块的代码,以求提高效率。