软件工程第四章——软件设计
软件设计
是软件生命周期中的一个活动
是进行软件编码的基础
是软件需求分析被转化为软件的内部结构
是连接用户需求和软件技术的桥梁
好的设计的特点
- 设计必须实现在分析模型中包含的所有明确要求,必须满足客户所期望的所有隐含要求
- 设计必须对编码人员、测试人员及后续的维护人员是可读可理解的
- 设计应提供该软件的完整视图,从实现的角度解决数据、功能及行为等各领域方面的问题
设计质量属性
- 功能性
- 易用性
- 可靠性
- 性能
- 可支持性(包括:扩展性,适应性,可维护性)
设计指导原则
- 设计应该是一种架构
- 设计应该是模块化的
- 设计应该包含数据、体系结构、接口和组件各个方面
应该设计出系统所用的数据结构
应该设计出展现独立功能特性的各组件
应该设计出各组件与外部环境连接的各接口
- 设计由软件需求分析过程中获得信息驱动,采用可重复使用的方法导出
- 设计应该采用正确清楚的表示法
设计相关概念
- 抽象
- 体系结构
- 设计模式
- 模块化
- 信息隐藏
- 功能独立
- 精化
- 重构
设计技术(面向过程)
数据设计
体系结构设计
系统需要执行的函数功能组件集(如数据库、计算模块)
组件之间通信、协同和合作的连接器
组件集成构成系统的约束
设计人员通过分析系统组成部分的已知特性,理解其整体特性的语义模型分析
体系架构组织与细化的基本问题
- 控制架构
- 数据传递
部署设计
输出部署架构,实施规范,实施计划
接口设计
结构化的总体设计方法
系统结构图中的模块
传入:
传入模块一从下属模块取得数据,经过某些处理,再将其传送给上级模块。它传送的数据流叫做逻辑输入数据流。
传出:
传出模块一从上级模块获得数据,进行某些处理,再将其传送给下属模块。它传送的数据流叫做逻辑输出数据流。
变换:
变换模块一它从上级模块取得数据,进行特定的处理,转换成其它形式,再传送回上级模块。它加工的数据流叫做变换数据流。
协调:
协调模块一对所有下属模块进行协调和管理的模块。
变换型系统结构图
事务性系统结构图
它接受一项事务,根据事务处理的特点和性质,选择分派一个适当的处理单元,然后给出结果。
在事务型系统结构图中,事务中心模块按所接受的事务的类型,选择某一事务处理模块执行。各事务处理模块并列。每个事务处理模块可能要调用若干个操作模块,而操作模块又可能调用若干个细节模块。
结构化组件设计
流程图
PDL程序设计语言(伪代码)
declare<数据名>as<限定词>
<限定词>具体的数据结构:
scalar<纯量>
array<数组>
list<列表>
char<字符>
structure<结构>
(2) 子程序结构
procedure<子程序名>
interface<参数表>
<分程序PDL语句>
return
end<子程序名> <PDL语句指各种PDL构造>
(3) 分程序结构
begin<分程序名>语句>
end<分程序名>
(4) 顺序结构
选择型:
if <条件> then
<语句>
else
<语句>
end if
if <条件> then
<语句>
else if <条件> then
<语句>
else
< 语句>
end if
WHILE循环:
loop while <条件>
语句>
end loop
UNTIL型循环:
loop until <条件>
<语句>
end loop
CASE型:
Case <选择句子> of
<标号>{,<标号}:>语言>
[defoult] :[语句>]
end case
(5) 输入/输出结构 print read display
判定表转换
面向对象设计
1.架构设计
架构设计的目的是要勾画出系统的总体结构,这项工作由经验丰富的架构设计师主持完成。
输入:用例模型、分析模型
输出:物理结构、子系统及其接口、概要的设计类
第一步 构造系统的物理模型
第二步 设计子系统
对于一个复杂的软件系统来说,将其分解成若干个子系统,子系统内还可以继续划分子系统或包,这种自顶向下、逐步细化的组织结构非常符合人类分析问题的思路。
每个子系统与其它子系统之间应该定义接口,在接口上说明交互信息,注意这时还不要描述子系统的内部实现。
划分子系统
按照功能划分,将相似的功能组织在一个子系统中
按照系统的物理布局划分,将在同一个物理区域内的软件组织为一个子系统
按照软件层次划分子系统,软件层次通常可划分为用户界面层、专用软件层、通用软件层、中间层和数据层
定义子系统之间的关系
“请求–服务”关系,“请求”子系统调用“服务”子系统,“服务”子系统完成一些服务,并且将结果返回给“请求”子系统。
平等关系,每个子系统都可以调用其它子系统。
如果子系统的内容相互有关联,就应该定义它们之间的依赖关系。在设计时,相关的子系统之间应该定义接口,依赖关系应该指向接口而不要指向子系统的内容。
如果两个子系统之间的关系过于密切,则说明一个子系统的变化会导致另一个子系统变化,这种子系统理解和维护都会比较困难
解决:
重新划分子系统,这种方法比较简单,将子系统的粒度减少,或者重新规划子系统的内容,将相互依赖的元素划归到同一个子系统之中
定义子系统的接口,将依赖关系定义到接口上
每个子系统的接口上定义了若干操作,体现了子系统的功能,而功能的具体实现方法应该是隐藏的,其他子系统只能通过接口间接地享受这个子系统提供的服务,不能直接操作它。
第三步 非功能性需求设计
分析阶段定义了整个系统的非功能需求,在设计阶段要研究这些需求,设计出可行的方案。
非功能需求包括:
系统的安全性、错误监测和故障恢复、可移植性和通用性等等
具有共性的非功能需求一般设计在中间层和通用应用层,目的是充分利用已有构件,减少重新开发的工作量。
2.用例设计
根据分析阶段产生的高层类图和交互图,由用例设计师研究已有的类,将它们分配到相应的用例中。
检查每个用例功能,依靠当前的类能否实现,同时检查每个用例的特殊需求是否有合适的类来实现。
细化每个用例的类图,描述实现用例的类及其类之间的相互关系其中的通用类和关键类可用粗线框区分,这些类将作为项目经理检查项目时的重点。
类的表示
类之间的关系
分析类图
细化用例
第1步:通过扫描用例中所有的交互图识别参与用例解决方案的类。在设计阶段完善类、属性和方法。例如,每个用例至少应该有一个控制
类,它通常没有属性而只有方法,它本身不完成什么具体的功能,只是起协调和控制作用。
每个类的方法都可以通过分析交互图得到,一般地检查所有的交互图发送给某个类的所有消息,这表明了该类必须定义的方法。例如“借
书控制”类向“读者”类发送“检查读者(读者编号)”消息,那么“检查读者”就作为“读者”类应该提供的方法。
第2步:添加属性的类型、方法的参数类型和方法的返回类型。
第3步:添加类之间的关系,包括关联、依赖、继承等。
UML顺序图
顺序图是强调消息时间顺序的交互图。
顺序图描述了对象之间传送消息的时间顺序,用来表示用例中的行为顺序。
顺序图将交互关系表示为一个二维图。即在图形上,顺序图是一张表,其中显示的对象沿横轴排列,从左到右分布在图的顶部;而消息则沿纵轴按时间顺序排序。创建顺序图时,以能够使图尽量简洁为依据布局。
- 对象
- 生命线
- 消息
- 激活
什么时候需要UML
当一个用例涉及多个类时
面向对象设计的四个层次
确定系统的总体结构和风格,构造系统的物理模型,将系统划分成不同的子系统。
中层设计:对每个用例进行设计,规划实现用例功能的关键类,确定类之间的关系。
进行底层设计:对每个类进行详细设计,设计类的属性和操作,优化类之间的关系。
补充实现非功能性需求所需要的类。