一.传统软件工程方法学采用结构化设计技术(SD)
从工程管理角度结构化设计分两步:
- 概要设计: 将软件需求转化为数据结构和软件系统结构。
- 详细设计:过程设计,通过对结构细化,得到软件详细数据结构和算法。(细化概要设计)
结构化分析得到的分析模型,与结构化设计的设计模型是密切相关的。
数据设计:数据模型及核心数据字典转变为数据结构。
体系结构设计:功能模型中数据流图转变成计算机模块框架。
接口设计:功能模型中数据流图转变成软件内部、软件与协作系统间、软件与用户间通信方式。
过程设计:行为模型及功能模型中的“处理规格说明”转换成软件构件过程描述。
二.结构化设计的概念与原理
1.模块化
模块“又称”构件”一般指用一个名字,调用的相邻程序元素序列。
模块化设计(modular design) :按适当的原则把软件划分为一个个较小的、相关而又相对独立的模块。
与“逐个击破”的原理类似,复杂度和工作量都会下降。
但是,考虑到在模块逐渐增多的过程中,模块之间的接口数量增加,因此并不是将模块划分得越细越好。
2.抽象 :抽出事物的本质特性,暂不考虑细节。(概要设计就是抽象的一个过程)
3.逐步求精:求精是指为了能集中精力解决主要问题,尽量推迟对细节问题的考虑,实际上是一个细化过程,与抽象是互补的概念。抽象使得设计者能够说明过程和数据,同时却忽略底层细节;求精帮助设计者在设计过程中揭示底层细节。
4.信息隐蔽:每个模块的实现细节对于其他模块来说是隐藏的也就是说,模块中所包含的信息是不允许其他不需要这些信息的模块访问的。每个客户只能通过接口来了解该模块,而所有的实现都隐蔽起来。——保证模块之间的关系相对简单
5.模块独立(利于分工):具有独立功能且和其他模块没过多作用。
采用该种设计过程的两条理由:
1.容易分工合作; 2.容易测试和维护,修改工作量较小,错误传播 范围小,扩充功能容易。
两个定性度量标准: 耦合和内聚。
三.模块独立
1.耦合:软件结构中不同模块间连接程度的度量——取决于模块之间的复杂程度与接口通过的数据量。
常见的耦合
- 非直接耦合:两个模块分别能独立地工作不需要另一模块存在。
- 数据耦合:两模块通过参数交换数据信息。(相对松散的耦合,本质上就是模块之间的数据传递)
- 控制耦合:两模块通过参数交换控制信息(包括数字形式) (影响另一个模块执行的流程)(相对紧密的耦合)
- 公共环境耦合:两个或多个模块通过一公共数据环境作用。
(1)数据耦合
两种情况:
(1)一模块送数据,另一模块取,等价数据耦合。
(2)两模块既往公共环境送又从里面取,介于数据耦合和控制耦合之间。
(2)内容耦合 (在设计过程中要竭力避免):
(1)一模块访问另一模块内部数据;
(2)一模块不通过正常入口转到另一模块内部;
(3)两模块有部分程序代码重叠(汇编程序);
(4)一模块有多个入口。
原则: 尽量使用数据耦合,少用控制耦合,限制公共环境耦合, 完全不用内容耦合。
2.内聚:模块内各元素彼此结合紧密程度。
(模块内部的数据元素结合得越紧密,势必会与其他模块的关系变得松散)
- 功能内聚 : 一模块中各部分是完成某一功能必不可少组成部分。
- 顺序内聚 :模块内处理元素同某功能密切相关,顺序执行。
- 通信内聚:一模块内各功能部分都使用相同输入数据,或产生相同输出数据。
- 过程内聚: 模块内处理元素相关,特定次序执行。
- 时间内聚:多为多功能模块,要求所有功能在同一时间内执行。如初始化模块和终止模块及紧急故障处理模块。
- 逻辑内聚:一模块完成功能在逻辑上属相同相似一类。
- 偶然内聚 :模块内各部分间没有联系,即使有也很松散。
内聚程度量级:
*优质系统所追求的应该是低耦合高内聚
四.启发规则(软件开发设计过程中所积累的一些经验)
1.改进软件结构提高模块独立性,初步结构分解或合并,降低耦合提高内聚。
2.模块规模应该适中:
过大:分解不充分,但进一步分解不应降低模块独立性。
过小:开销大于有效操作,模块数目过多系统接口复杂。
通常语句行数在50~100(一页纸),最多不超过500行。
3.深度、宽度、扇出和扇入应适当
- 深度:软件结构控制层数,标志一系统大小和复杂程度。
- 宽度:软件结构同一层模块数最大值,越大系统越复杂。
- 扇出: 一模块直接控制(调用)模块数,过大,模块复杂,过小(如1)不好。
- 扇入: 有多少上级模块直接调用它,越大共享该模块上级模块越多(扇出扇入不合适改善)
4.模块作用域应在控制域内
- 作用域:受该模块内判定影响的所有模块集合。
- 控制域:模块本身及所有直接或间接从属它的模块集合。若模块作用域不在控制域内,会增大模块间控制耦合。
如上图,C D E之间发生了控制耦合。
(上述为两种解决方式)
5.降低模块接口复杂程度(接口设计越简单越好)
6.设计单入口、单出口模块——避免内容耦合
7.模块功能可预测(不能生成不可预测的模块,因为不能测试)
此外,也不能设计功能过分受限的模块。(即为开发过程中写死的数据部分)
五.面向数据流的设计方法
面向数据流的设计要解决的任务,就是将软件需求分析阶段生成的逻辑模型数据流图映射(Mapping)表达软件系统结构的软件结构图。 结构化设计属于面向数据流的设计方法。
1.软件结构图:
(1)模块--在SC图中用矩形框表示,并用名字来标记它
(2)模块的调用关系和接口
2.信息流的类型:
变换流:信息沿输入通路进入系统,由外部形式变换成内部形式,通过变换中心加工处理后再沿输出通路变换成外部形式离开软件系统(比如制止的票据变化为数据信息存储在电脑之中,然后再通过查询结果实现输出)。
事务流 信息沿输入通路到一处理,由处理根据输入信息类型在若干动作序列中选一个执行。
处理称事务中心,完成任务:
(1)接收输入信息(又称事务);
(2)分析每个事务确定类型;
(3)根据事务类型选取一活动通路。
3.面向数据流设计过程(将各种数据流图映射为软件结构图)
4.变换分析(映射变换型):将具有变换流特点的数据流图映射成软件结构。
(1)复查基本系统模型 确保系统输入和输出数据符合实际。
(2)复查并精化数据流图 正确、处理项完成相对独立功能。
(3)确定数据流图具有变换特性还是事务特性 ——没有明显事务中心,为变换型。
(4)找出变换中心 ,确定数据流边界。
(5)完成一级分解
(6)完成第二级分解
5.事务分析(映射事务型):
信息流有明显事务特点(事务中心),采用事务分析方法。
软件结构:一接收分支和一发送分支。
(设计出的软件系统,模块与模块之间传递的基本上都是数据信息,也就是形成了数据耦合)
六.人机界面设计
1.设计问题:
(1)系统响应时间 从用户完成某控制动作,到软件给出预期响应。
两个重要属性:长度和易变性。
关于长度:
过长用户感到不安、沮丧
用户觉得系统立即响应时间范围0.1-1秒,超出1秒会让用户注意到延迟
时间较长时的应对措施:
- 1-10 秒 鼠 标 显 示 成 为 沙 漏
- 10 到18 秒 由微帮助来显示处理进度
- 18 秒 以 上 显示处理窗口,或显示进度条
过短迫使用户加快操作节奏,导致出错。
关于易变性: 易变性指响应时间相对平均响应时间偏差,越低越好,否则会让用户误认为系统工作异常。
(2)用户帮助措施——容易对软件产生好感
手册和联机帮助(不离开用户界面)。
- 联机帮助两类:集成帮助和附加帮助。集成帮助设计在软件里面,附加帮助系统建成后加到软件中,前者可用性更强。
- 请求帮助的方式:帮助菜单,特殊功能键,HELP 命令。
- 显示帮助信息方式:独立窗口,参考某个文档,屏幕固定位置作简短提示
- 组织帮助信息方式:平面结构,通过关键字访问;层次结构,查更详细信息;超文本结构
(3)出错信息处理
- 采用用户可以理解术语;
- 提供清楚、易理解报错信息(出错位置、原因);
- 从错误中恢复的建设性意见;
- 信息用颜色等在视觉上引人注目;
- 告诉用户可能造成负面后果。
(4)命令交互
- 建议保留命令交互方式:
- 控制序列:Ctrl-C(拷贝) Ctrl-H(帮助) Ctrl-P(打印) 功能键:F1(帮助)
- 键入命令命令宏机制:用户定义名字代表一个常用命令序列。
2.设计指南
(1)一般交互
- 保持人机界面菜单选择、命令输入、数据显示风格一致——便于用户快速熟悉软件;
- 提供有意义信息反馈:双向通信;
- 破坏性动作前要确认:删除、覆盖;
- 减少两次操作之间必须的记忆量;
- 提高对话、移动和思考的效率(相近的操作不要离得太远);
- 允许犯错误:保护不受致命错误破坏;
- 按功能对动作分类,设计屏幕布局;
- 提供帮助措施;用简单的动词或动词短语作为命令名。
(2) 信息显示:
- 显示与当前工作有关信息;
- 简单易懂方式表示数据:图形、图表;
- 使用一致标记、标准缩写和可预知颜色;
- 产生有意义出错信息——知道产生错误的原因
- 使用模拟的方式显示信息等。
(3)数据输入
- 减少用户输入动作:鼠标选择、滑动标尺等;
- 使当前不适用命令不起作用——保证用户不会犯错误;
- 交互灵活:保留各种输入方式;
- 让用户控制交流;
- 对所有输入都提供帮助(比如提示学号前4位是2020);
- 消除冗余输入:数据单位、整钱后键入.00、提供缺省值等。
七.过程设计
1.任务:
- 确定模块算法
- 确定模块使用数据结构
- 确定模块接口(系统外部接口、用户界面、内部模块间接口细节、输入数据和输出数据)
(概要设计:主要是为了得出软件结构——过程设计则是对每一个模块进行细化)
2.结构化的程序设计:结构化程序设计技术是过程设计一关键技术。
经典定义: 程序代码通过顺序、选择、循环三种控制结构连接,单入口单出口。
扩展定义: 可限制使用GOTO语句、DO_UNTIL和DO_CASE(goto语句过于灵活,会导致软件系统颇为复杂)
修正定义: LEAVE和BREAK,可从循环中转移出来。
3.程序流程图:历史最悠久、使用最广泛的过程设计工具。
优点: 对控制流程描绘直观,便于初学者掌握。
缺点: (1)不是逐步求精好工具,过早考虑控制流程, 非整体结构;
(2)用箭头代表控制流,程序员随意转移控制;
(3)不易表示数据结构和调用关系。
4.N-S图:
特点:
(1)功能域(一特定控制结构的作用域)明确;
(2)不可能任意转移控制(图中没有流线)
;(3)容易确定局部和全程数据的作用域;
(4)容易表现嵌套关系,也可表示模块的层次结构。
5.PAD图:
优点:
(1)使用PAD图设计的程序必然是结构化程序——因为不提供控制流线让程序随意地流转;
(2)PAD图描绘的程序结构十分清晰;
(3)用PAD图表现程序逻辑,易读、易懂、易记;
(4)容易将PAD图转换成高级语言源程序——标准化程度很高;
(5)支持自顶向下逐步求精。——即逐渐将某个图的细节进一步细化
6.判定表(适用于判断步骤多的流程)
左上部列出所有条件; 左下部所有可能做的动作; 右上部表示各种条件组合的一矩阵; 右下部是和每种条件组合相对应的动作。
如上图很细致地反应了行李托运的判定表
7.判定树:判定表变种,表示复杂条件组合与应做动作间对应关系
优点: 形式简单,易看出含义,易于掌握和使用。
缺点: 简洁性不如判定表,相同数据元素重复写多遍,越接近叶端重复次数越多。
8.伪码(PDL)(过程设计语言)(结构化语言):用正文形式表示数据和处理过程设计工具。
PDL具有严格关键字外部语法,定义控制结构和数据结构; PDL表示实际操作和条件的内部语法灵活自由,适应各种工程项目需要。
9.程序复杂度——介绍使用比较广泛的McCabe方法(通过控制流程来度量)。
(1)根据过程设计结果画出相应流图 流图描述程序控制流,基本图形符号如下图所示。(绘制过程中要尽量简化,比如将判断结点拆分)
(2)计算流图的环形复杂度三种方法:
V(G)=区域数
V(G)=E-N+2 E为流图中边数,N为流图中节点数
V(G)=P+1 P为判定点数
八.面向数据结构设计方法——从数据结构出发,设计出程序结构
数据结构既影响程序的结构也影响程序的处理过程,可从数据结构导出程序的处理过程,适合详细设计。
面向数据结构设计方法两种: Jackson和Warnier方法
1.Jackson图(可以表达数据结构亦或是程序结构)
2.Jackson方法
步骤:
1.确定输入数据和输出数据逻辑结构(经过概要设计后已知),用Jackson图表达;
2.确定输入结构和输出结构中有对应关系(因果)的单元——一定要严格对应;
3.描绘数据结构的Jackson图导出描绘程序结构Jackson图;
4.列出所有操作和条件,分配到Jackson图中;
5.用伪码表示。