目的是建立一个符合用户要求的软件系统;
这个阶段我们将数据流图改造成初识结构图;
实际上是为编程制定一个周密的计划;
我们将要发现软件设计阶段和需求分析阶段的区别:
需求分析的对象是现实系统,从现实系统构造出一个逻辑上描述了现实系统的模型;
软件设计阶段的对象是尚且不存在的软件,或者说是需求分析阶段得到的模型,为这
个模型对应的软件的编写制定计划和详细说明;
需要设计的内容:
1, 软件系统的结构:数据结构(数据库),程序结构;
2, 模块:模块就是用一个名字可以调用的一段程序语句;
模块:组成软件系统的最小单位,应该具有输入和输出,功能,内部数据,程序代码;
我们设计的顺序应该是先确定模块的外部特性(输入输出,功能),再确定内部特性(内部数据和程序代码);
所以我们发现平时我写程序的一个非常不好的习惯:总是尽量去写代码和组织内部数据,等这一切搞完了,才会发现自然出现的输入输出和功能,这是非常ugly的做法;
概要设计:
基本任务:
将系统划分为模块;
决定每个模块的功能;
决定模块的调用关系;
决定模块的界面,也就是模块间传递的数据;
主要工作是分解模块,确定系统的模块层次结构;
概要设计需要交付的文档:
1, 数据结构的描述部分;
2, 模块说明部分,它包括模块结构图以及每个模块的功能说明;
结构化设计方法:
继承了结构化分析方法SA,称为SD;
什么是良好的程序系统:
块间联系:是对模块独立性的直接衡量,块间联系越小就意味着模块的独立性越高;
块内联系:语句与语句(段)之间的联系,块内联系越大就意味着模块的独立性越高;
所以我们的目标是:块间联系小,块内联系大;
从人群的角度可以这样理解:如果一个国家追求的目标是独立性,那么它与别国之间的联系(这里的联系指依赖性而不是通信)应该越小,并且在国家内部人与人之间的联系应该越大,那代表团结;
SD方法的基本思想:将系统设计成由相对独立,单一功能的模块组成的结构;
相对独立,单一功能的好处:
每个模块可以独立地被理解,编程,测试,排错,修改;错误的蔓延范围也可以限制
在一个模块中;
概要设计的描述方式是结构图:
结构图的组成:
1,模块:方框表示
2,调用:箭头;
3,数据:写在调用上,表示模块与模块之间发生调用时传递的数据;
4,判断:
5,重复:
注意:一个同样的模块在一个结构图中只能出现一次;
画结构图的习惯:输入模块在左边,输出在右边,计算处理模块在中间;
SD方法的步骤:从数据流图到初识结构图;
对结构图进行改进;
块间联系和块内联系:
块间联系的大小的衡量:
1, 块间的联系方式—块间以什么方式来调用,分两种:
第一:用过程语句调用,通过模块的名字调用整个模块;
第二:直接引用,一个模块直接存取另一个模块内部的信息;
很显然,直接引用导致了块间的联系太大:界面不清楚,对某个模块理解的同时还需要理解其他的模块;修改一个模块可能涉及到其他的模块,排错的时候也一样;
所以一定要记住:模块之间的调用应该通过过程语句调用;
2, 共用信息的作用: 如果共用信息既做控制信息,又做数据,那么块间联系最高;
所以记住:模块之间的公用信息应该只作为数据而不要做控制信息;
比如下面的a图就没有b图效果好:
好的做法是:模块只引用其调用模块显式传送给它的参数以及它本身的局部变量;
如果达到块间联系最小?
原则一:每个模块同过程语句(或者函数)调用其他模块;
原则二:模块间传递的参数作数据用;
原则三:模块间共用的信息(如参数)尽量少;
块内联系:SD的原则是--------模块分解时应该尽量把相互有密切联系的成分划分在同一个模块,而不要把不相关的成分凑到一个模块中;
块内联系常见的类型:
1,偶然型:组成模块的成分纯属偶然,没有必然联系;
不宜修改,模块含义不容易理解,难以测试;
3, 逻辑型:将几个逻辑上相似但没有联系的功能放到一个模块中
比如下图:
在该图中,把a改造成b显然不是好的做法,因为对b来说需要如c图中显示的查两次开关值,而a只需要查一次开关,就行了,不需要对究竟执行A,B,C的哪个进行判定;
4, 瞬时型: 将需要同时执行的成分放到同一个模块中;如初始化模块或结束模块,
而这些模块之间并没有联系;
5, 通讯型:模块中的成分引用共同的数据:
复用性差,各成分的执行次序可以是任意的,这表示块间联系比较弱;
6, 顺序型:
模块中的某个成分的输出做为下一个成分的输入;复用性差;
7, 功能型:一个模块包括并仅包括为完成某一个具体功能所必须的所有成分;
优点:界面清晰,易于理解,同其他模块的联系较低;复用性好;
越是底层的模块,越容易做成功能型的模块;
所以SD的设计原则是:
原则一:使每个模块执行一个功能;
原则二:每个模块同过程语句(或者函数)调用其他模块;
原则三:模块间传递的参数作数据用;
原则四:模块间共用的信息(如参数)尽量少;
设计技巧:
改进结构图的途径就是:减少块间联系;提高块内联系;
如果一个模块的篇幅比较大,可以从中抽出一些功能构成它的下层模块;
如果一个模块的篇幅比较小,可以将它同其调用模块合并;
尽可能研究整张结构图;
初识结构图可以暂时不满足系统说明书中的某些要求,而在改进过程中使这些要求逐
步得到满足,因为越到后面,结构图的可维护性越好,局部的改动不会影响整个大局;
功能型的模块的组成:
执行某项具体任务的部分;
通知它的调用模块发生了例外情况的部分;
在数据结束时通知调用模块文件结束的部分;
经验是:
如果相同的成分的不同拷贝出现在了两个不同的模块中,则带来的修改时的同步修改问题:
很显然c图的方法更好;b,c,d,e都是对a图的修改,意义是消除重复功能;
作用范围和控制范围的讲解:
一个判定的作用范围:所有受这个判定影响的模块的集合;
一个模块的控制范围:它本身以及其所有的下属模块;
SD方法的原则是作用范围应该是控制范围的子集;
个人觉得搞出一个作用范围和一个控制范围是非常ugly的术语,你就这样记着:控制范围比作用范围大;
B2中的判定的作用在A上,然而它的控制范围(B2)中却没有A;
TOP中的判定的作用在A和B2上,虽然A和B2都在TOP的控制范围内,但是层次上的距离太远;
虽然这个是合理的,但是总是觉得要么是B2离Y太远,要么是A太上层以至于当我们移动Y中的判定到B时,又会出现一中描述的情景:作用范围不在控制范围内;
这个非常理想:控制范围包含了所有的作用范围,并且控制范围内的模块都是直接下属;
如果作用范围不在控制范围之内的解决之道:
1, 将作判定的模块合并到它的调用模块中,直到使判定处于足够高的位置;
2, 将受判定影响的模块下移到控制范围内;下移的缺点是增加了参数的传递;
3, 把判定上移到足够高的位置;跟第一个策略非常相似,但是不同于一的是它并不把牵连到的模块给合并了,只是移动判定;
模块的大小:指源代码的行数;合适的为50---100行;
原则:对于大的模块,检查是否可以分离出一些功能来构成同层或下一层的其他模块;
对于小的模块,检查是否同它的调用模块合并;
模块的扇出和扇入:
一个模块调用其他模块的个数,称为模块的扇出,扇出越大,该复杂性越大;合适为7;
一个模块被其他模块调用的个数,成为该模块的扇入,扇入越大,不会影响该问题的复杂性,反而说明这个模块的复用性好;
重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要
从数据流图导出初识结构图:SA方法在需求分析阶段得到了数据流图,SD方法将在设计阶段以该数据流图来构造初识的模块结构图;
原则都是先设计模块的顶端的主模块,然后“自顶向下逐步细化”…
每创建一个新的模块时需要考虑:
该模块做什么;
模块同其调用模块之间的界面,即传递的参数;
数据流图一般有两种典型的结构:
1, 变换型结构:通过变换分析导出结构图
该变换型的数据流图的特点:输入,主加工,输出;
变换分析的步骤:
首先,找出主加工,确定逻辑输入,逻辑输出;
然后,设计模块结构的顶层和第一层;第一层的各个模块应该分别代表:输入,主加工,输出;
然后,设计中,下层模块;
例子:
设计时应该始终思考:子模块如何实现父模块的期望并且只做本分的,别忘了自己也可以把某些期望留给自己的子模块;最后达到的效果就是在一个模块的所有子模块中只有一个模块是描述加工的;在整个过程中,应该写上每个调用对之间传递的参数;
该图中X,Y,Z的顺序很不好决定,默认为:自上而下,自左到右;
2, 事务型结构:通过事务分析导出结构图
这个事务型数据流图的特点:输入是同一个,然后进行分类加工,最后同义输出;
最不同于变换型的是:它的多次加工可以走不同的路径;
例子:
发现事务型的数据流图转换为结构图的思路非常明确;
我们发现,其实加工在结构图中得到了体现;
例子:
设计原则是:以变换分析为主,事务分析为辅;
重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要重要
SD方法从以下5个方面获得质量良好的软件结构:
1, 根据描述用户需求的数据流图导出了实现用户需求的结构图;
2, 将系统分解为多个黑盒;将黑盒组织成适合于用计算机实现的层次结构;
3, 用块间联系和块内联系作为评价软件结构质量的标准;
4, 给出一组设计技巧,如扇入和扇出,模块大小的掌握,作用范围和控制范围;
5, 用结构图直观地描述软件结构,因此易于理解,并直接可以用于评价,分析和复查等;
SD方法的不足:SD只考虑程序结构的设计而没有考虑数据结构的设计;
概要设计的其他工作:
1, 设计文档:结构图;每个模块的描述;数据库,文件结构,全程数据描述;需求/设计交叉表;测试计划;
2,概要设计复查:需求的可追溯新,方案的清晰性;
详细设计
概要设计将软件系统分解成为多个模块,并决定每个模块的外部特征(怎么做),即功能和界面;
详细设计确定每个模块的内部特征,即怎么做;
“怎么做“通常有以下三种描述方式:
继承概要设计的SD方法,详细设计用SP方法,即结构化程序设计方法;
主程序员组:
主程序员;
后备程序员;
初级程序员 ;
所以说软件工程中用到人员多了:
在需求分析阶段SA用到的分析员;
在概要设计阶段SD用到的设计员;
在详细设计阶段SP用到的程序员;
SP用的工具:
1, 流程图:
流程图只能描述执行过程,但不能对有关的数据进行描述;
2, 盒图:
NS图只有一个入口和一个出口,所以它限制了随意的控制转移,保证了程序的良好结构;
一个例子:
NS图应该用两个盒子:数据盒和模块盒;
NS图的缺点是手工修改比较麻烦;
3, 问题分析图(PAD):
基本成分:
PAD的规则:走树;通过走树可以从PAD直接产生程序,该过程便于用计算机自动实现;
4,程序设计语言:PDL;
特点是:外层语法(控制流程的if,then之类的)是确定的,内层语法是不确定的;
缺点是:没有图形直观;
Jackson方法:
SA,SD,SP方法用于需求分析阶段和设计阶段,是面向数据流的;
而Jackson方法是一种面向数据结构的方法,适用于数据处理类问题,特别是企业事业管理的一类软件系统;
Jackson方法的原则是:使程序结构同数据结构相对应;
Jackson的三种结构:
1, 顺序结构:
2, 选择结构:
3, 重复结构:
例子:
对于上面的表,这样一个数据结构Jackson方法的描述如下:
所以实际上我们发现程序结构和数据结构是一一对应的;
Jackson的步骤:
一:建立数据结构;相当于结构化的SA(需求分析)
二:以数据结构为基础建立程序结构;相当于结构化的SD(概要设计);
三:列出各种操作,并分配到适当的模块中;相当于结构化的SP(详细设计);
Jackson方法 缺点:比较大的系统涉及到的输入输出太多,只能用SD方法设计整个结构,然后用Jackson方法来设计局部模块,从而结合使用;
注意:块间联系和块内联系同样适用于Jackson的评价;
数据结构经常变换,那么Jackson方法设计出来的程序结构也需要经常改变;