1 总体设计
总体设计通常由两个主要阶段组成:
系统设计阶段,确定系统的具体实现方案;
结构设计阶段,确定软件结构。
总体设计的9个步骤:
1.设想供选择的方案
考虑各种可能的实现方案,一般将需求分析阶段得出的数据流图作为出发点,把数据流图中的处理分组的各种可能性,抛弃在技术上行不通的分组方法,余下的分组方法代表可能的实现策略,并且可以启示供选择的物理系统。
2.选取合理的方案
选取若干个合理的方案,通常至少选取低成本/中成本/高成本的3种方案。
每个方案准备四份资料(系统流程图,组成系统的物理元素清单,成本/效益分析,实现这个系统的进度计划)。
3.推荐最佳方案
从合理方案中,推荐一个最佳的方案,并且为这个方案制定详细的实现计划。
4.功能分解
从实现角度把复杂的功能进一步分解,一般说来,经过分解之后应该使每个功能对大多数程序员而言都是明显易懂的。功能分解导致数据流图的进一步细化。
5.设计软件结构
把模块组织成良好的层次系统,顶层模块调用它的下层模块以实现程序的完整功能。
6.设计数据库
7.制定测试计划
考虑测试问题,在设计的时候注意提高软件的可测试性。
8.书写文档
系统说明:主要内容包括用系统流程图描绘的系统构成方案,组成系统的物理元素清单,成本/效益分析;对最佳方案的概括描述,精化的数据流图,用层次图或结构图描绘的软件结构,用IPO图或其他工具简要描述的各个模块的算法,模块间的接口关系,以及需求、功能和模块三者之间的交叉参照关系等。
用户手册:根据总体设计阶段的结果,修改更正在需求分析阶段产生的初步的用户手册。
测试计划:包括测试策略,测试方案,预期的测试结果,测试进度计划等等。
详细的实现计划:
数据库设计结果:
9.审查和复查
技术审查,然后由客户从管理角度进行复查。
2 设计原理
2.1 模块化
模块是由边界元素限定的相邻程序元素的序列,而且有一个总体标识符代表它。按照模块的定义,过程、函数、子程序和宏等,都可作为模块。面向对象方法学中的对象是模块,对象内的方法也是模块。
每个程序都相应地有一最适当的模块数目M,使得系统的开发成本最小。当模块数目增加时每个模块的规模将减小,开发单个模块需要的成本确实减少了;但是,随着模块数目增加,设计模块间接口所需要的工作量也将增加。
2.2 抽象
抽象就是抽出事物的本质特性而暂时不考虑它们的细节。
由于人类思维能力的限制,如果每次面临的元素太多,是不可能产生精确思维的。处理复杂系统的唯一有效的方法是用层次的方式构造和分析它。
当考虑对任何问题的模块化解法时。可以提出许多抽象的层次。在抽象的最高层次使用问题环境的语言,以概括的方式叙述问题的解法;在较低抽象层次采用更过程化的方法,把面向问题的术语和面向实现的术语结合起来叙述问题的解法;最后,在最低的抽象层次用可以直接实现的方式叙述问题的解法。
2.3 逐步求精
逐步求精是人类解决复杂问题时采用的基本方法。为了能集中精力解决主要问题而尽量延迟对问题细节的考虑。
Miller法则:一个人在任何时候都只能把注意力集中在(7±2)个知识块上。
逐步求精是一种自顶向下的设计策略,按照这种设计策略,程序的体系结构是通过逐步精化处理过程的层次而设计出来的。
抽象与求精是一对互补的概念。抽象使得设计者能够说明过程和数据,同时却忽略了底层细节。求精则帮助设计者在设计过程中桌布揭示出低层细节。
2.4 信息隐藏和局部化
信息隐藏原理指出:应该这样设计和确定模块,使得一个模块内包含的信息(过程和数据)对于不需要这些信息的模块来说,是不能访问的。
局部化是指把一些关系密切的软件元素物理地放得彼此靠近。
3 耦合和内聚
耦合衡量不同模块彼此间相互依赖(连接)的紧密程度;内聚衡量一个模块内部各个元素彼此结合的紧密程度。
3.1 耦合
如果两个模块中的每一个都能独立地工作而不需要另一个模块的存在,那么它们彼此完全独立,这意味着模块间无任何连接,耦合程度最低。
数据耦合:低耦合,如果两个模块彼此间通过参数交换信息,而且交换的信息仅仅是数据,那么这种耦合称为数据耦合。系统中必须存在这种耦合,因为只用当某些模块的输出数据作为另一些模块的输入数据时,系统才能完成有价值的功能。
控制耦合:中等耦合,如果传递的信息中有控制信息(尽管有时这种控制信息以数据的形式出现),则称为控制耦合。
特征耦合:如果被调用的模块需要使用作为参数传递进来的数据结构中的所有元素,那么,把整个数据结构作为参数传递就是完全正确的。但是,当把整个数据结构作为参数传递而被调用的模块只需要使用其中一部分数据元素时,就出现了特征耦合。在这种情况下,被调用的模块可以使用的数据多余它确实需要的数据,这将导致对数据的访问失去控制,从而给计算机犯罪提供了机会。
公共环境耦合:当两个或多个模块通过一个公共数据环境相互作用时,它们之间的耦合成为公共环境耦合。公共环境耦合的负责程度随耦合的模块个数而变化,当耦合的模块个数增加时复杂程度显著增加。
内容耦合:最高程度的耦合。一个模块方位另一个模块的内部数据。一个模块不通过正常入口而转到另一个模块的内部。两个模块有一部分程序代码重叠(只可能出现在汇编程序中)。一个模块有多个入口(这意味着一个模块有几种功能)。
尽量使用数据耦合,少用控制耦合和特征耦合,限制公共环境耦合的范围,完全不用内容耦合。
3.2 内聚
内聚标识着一个模块内各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。
内聚和耦合是密切相关的,模块内的高内聚往往意味着模块间的耦合。内聚和耦合是进行模块化设计的有力工具,但是实践表明内聚更重要,应该把注意力集中到提高模块的内聚程度上。
低内聚有如下几类:
偶然内聚:如果一个模块完成一组任务,这些任务彼此间即时有关系,关系也是很松散,就叫做偶然内聚。
逻辑内聚:如果一个模块完成的任务在逻辑上属于相同或相似的一类。
时间内聚:如果一个模块包含的任务必须在同一段时间内完执行。
中内聚有两类:
过程内聚:如果一个模块内的处理元素是相关的,而且必须以特定次序执行。
通信内聚:如果模块中所有元素都使用同一个输入数据和(或)产生同一个输出数据。
高内聚有两类:
顺序内聚:如果一个模块内的处理元素和同一个功能密切相关,而且这些处理必须顺序执行。
功能内聚:如果模块内所有处理元素属于一个整体,完成一个单一的功能。
功能内聚 | 10分 | 时间内聚 | 3分 |
顺序内聚 | 9分 | 逻辑内聚 | 1分 |
通信内聚 | 7分 | 偶然内聚 | 0分 |
过程内聚 | 5分 |
4 启发规则
1.改进软件结果提高模块独立性。
2.模块规模应该适中。
3.深度、宽度、扇出和扇入都应适当。
4.模块的作用域应该在控制域之内。
5.力争降低模块接口的复杂程度。
6.设计单入口单出口的模块。
7.模块功能应该可以预测。