《软件工程导论》常见图汇总
無間之鍾
2021年12月19日 20:28

传统方法学

可行性研究

系统流程图

系统流程图是概括地描绘物理系统的传统工具。

基本思想:

用图形符号以黑盒子形式描绘组成系统的每个部件(程序、文档、数据库、人工过程等)。

系统流程图表达的是数据在系统各部件之间流动的情况,而不是对数据进行加工处理的控制过程,因此尽管系统流程图的某些符号和程序流程图的符号形式相同,但是它却是物理数据流图而不是程序流程图。

利用符号可以把一个广义的输入输出操作具体化为读写存储在特殊设备上的文件(或数据库),把抽象处理具体化为特定的程序或手工操作等。

以概括的方式抽象地描绘一个实际系统时,仅仅使用图中列出的基本符号就足够了。

需要更具体地描绘一个物理系统时还需要使用图中列出的系统符号

数据流图

数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输入移动到输出的过程中所经受的变换。

在数据流图中没有任何具体的物理部件,它只是描绘数据在软件中流动和被处理的逻辑过程。数据流图是系统逻辑功能的图形表示,即使不是专业的计算机技术人员也容易理解它,因此是分析员与用户之间极好的通信工具。此外,设计数据流图时只需考虑系统必须完成的基本逻辑功能,完全不需要考虑怎样具体地实现这些功能,所以它也是今后进行软件设计的很好的出发点。

数据流四种基本符号

  • 正方形表示数据的源点或终点

  • 圆角矩形代表变换数据的处理

  • 开口矩形代表数据存储

  • 箭头表示数据流,即特定数据的流动方向

附加符号

需求分析

实体-联系图

通常,使用实体-联系图(entity-relationship diagram)来建立数据模型。可以把实体联系图简称为E-R图,相应地可把用E-R图描绘的数据模型称为E-R模型。

E-R图中包含了实体(即数据对象)、关系和属性3种基本成分,通常用矩形框代表实体,用连接相关实体的菱形框表示关系,用椭圆形或圆角矩形表示实体(或关系)的属性,并用直线把实体(或关系)与其属性连接起来。

E-R模型可以作为用户与分析员之间有效的交流工具。

状态转换图

状态转换图(简称为状态图)通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。此外,状态图还指明了作为特定事件的结果,系统将做哪些动作。

状态

状态是任何可以被观察到的系统行为模式,一个状态代表系统的一种行为模式。状态规定了系统对事件的响应方式。

在状态图中定义的状态主要有:初态(即初始状态)、终态(即最终状态)和中间状态。在一张状态图中只能有一个初态,而终态则可以有0至多个。

状态图既可以表示系统循环运行过程,也可以表示系统单程生命期。

事件

事件是在某个特定时刻发生的事情,它是对引起系统做动作或(和)从一个状态转换到另一个状态的外界事件的抽象。

事件就是引起系统做动作或(和)转换状态的控制信息。

符号

在状态图中,初态用实心圆表示,终态用一对同心圆(内圆为实心圆)表示。

中间状态用圆角矩形表示,可以用两条水平横线把它分成上、中、下3个部分。上面部分为状态的名称,这部分是必须有的;中间部分为状态变量的名字和值,这部分是可选的;下面部分是活动表,这部分也是可选的。

活动表的语法格式如下:

事件名(参数表)/动作表达式

其中,“事件名”可以是任何事件的名称。

在活动表中经常使用下述3种标准事件:entry, exit和do。entry事件指定进入该状态的动作,exit事件指定退出该状态的动作,而do事件则指定在该状态下的动作。需要时可以为事件指定参数表。活动表中的动作表达式描述应做的具体动作。

状态图中两个状态之间带箭头的连线称为状态转换,箭头指明了转换方向。状态变迁通常是由事件触发的,在这种情况下应在表示状态转换的箭头线上标出触发转换的事件表达式;如果在箭头线上未标明事件,则表示在源状态的内部活动执行完之后自动触发转换。

事件表达式的语法如下:

事件说明[守卫条件]/动作表达式

其中,事件说明的语法为:

事件名(参数表)

状态图中使用的主要符号

其他图形工具

描述复杂的事物时,图形远比文字叙述优越得多,它形象直观容易理解。前面已经介绍了用于建立功能模型的数据流图、用于建立数据模型的实体-联系图和用于建立行为模型的状态图,本节再简要地介绍在需求分析阶段可能用到的另外3种图形工具。

层次方框图

层次方框图用树形结构的一系列多层次的矩形框描绘数据的层次结构。

随着结构的精细化,层次方框图对数据结构也描绘得越来越详细,这种模式非常适合于需求分析阶段的需要。系统分析员从对顶层信息的分类开始,沿图中每条路径反复细化,直到确定了数据结构的全部细节时为止。

Warnier图

和层次方框图类似,Warnier图也用树形结构描绘信息,但是这种图形工具比层次方框图提供了更丰富的描绘手段。

用Warnier图可以表明信息的逻辑组织,也就是说,它可以指出一类信息或一个信息元素是重复出现的,也可以表示特定信息在某一类信息中是有条件地出现的。

  • 花括号用来区分数据结构的层次,在一个花括号内的所有名字都属于同一类信息

  • 异或符号(⊕)表明一类信息或一个数据元素在一定条件下才出现,而且在这个符号上、下方的两个名字所代表的数据只能出现一个

  • 在一个名字下面(或右边)的圆括号中的数字指明了这个名字代表的信息类(或元素)在这个数据结构中重复出现的次数。

IPO图

IPO图是输入、处理、输出图的简称,它是由美国IBM公司发展完善起来的一种图形工具,能够方便地描绘输入数据、对数据的处理和输出数据之间的关系。

改进的IPO图

改进的IPO图的形式加信息主要有系统名称、图的作者,完成的日期,本图描述的模块的名字,模块在层次图中的编号,调用本模块的模块清单,本模块调用的模块的清单,注释,以及本模块使用的局部数据元素等。在需求分析阶段可以使用IPO图简略地描述系统的主要算法(即数据流图中各个处理的基本算法)。当然,在需求分析阶段,IPO图中的许多附加信息暂时还不具备,但是在软件设计阶段可以进一步补充修正这些图,作为设计阶段的文档。这正是在需求分析阶段用IPO图作为描述算法的工具的重要优点。

形式化说明技术

有穷状态机

一个有穷状态机可以表示为一个5元组(J, K, T, S, F),其中

  • J是一个有穷的非空状态集

  • K是一个有穷的非空输入集

  • T是一个从(J-F)×K到J的转换函数

  • S∈J,是一个初始状态

  • F⊆J,是终态集

为了对一个系统进行规格说明,通常都需要对有穷状态机做一个很有用的扩展,即在前述的5元组中加入第6个组件——谓词集P,从而把有穷状态机扩展为一个6元组,其中每个谓词都是系统全局状态Y的函数。转换函数T现在是一个从(J-F)×K×P到J的函数。

有穷状态机方法采用了一种简单的格式来描述规格说明:

当前状态+事件+谓词=>下个状态

Petri 网

Petri网包含4种元素:

  • 一组位置P

  • 一组转换T

  • 输入函数I

  • 输出函数O

Petri网的标记是在Petri网中权标(token)的分配。

对Petri网的一个重要扩充是加入禁止线。如图所示,禁止线是用一个小圆圈而不是用箭头标记的输入线。

总体设计

层次图和 HIPO 图

层次图用来描绘软件的层次结构。数据结构的层次方框图相同,但是表现的内容却完全不同。层次图很适于在自顶向下设计软件的过程中使用。

HIPO图是美国IBM公司发明的“层次图加输入/处理/输出图”的英文缩写。为了能使HIPO图具有可追踪性,在H图(层次图)里除了最顶层的方框之外,每个方框都加了编号。

结构图

Yourdon提出的结构图是进行软件结构设计的工具。图中一个方框代表一个模块,框内注明模块的名字或主要功能;方框之间的箭头(或直线)表示模块的调用关系。尾部是空心圆表示传递的是数据,实心圆表示传递的是控制信息。

一些附加的符号,可以表示模块的选择调用或循环调用。左图表示当模块M中某个判定为真时调用模块A,为假时调用模块B。右图表示模块M循环调用模块A、B和C。

详细设计

过程设计的工具

程序流程图

程序流程图又称为程序框图,它是使用最广泛的描述过程设计的方法。程序流程图中使用的符号(a) 选择(分支); (b) 注释; (c) 预先定义的处理; (d) 多分支; (e) 开始或停止; (f) 准备; (g) 循环上界限; (h) 循环下界限; (i) 虚线; (j) 省略符; (k) 并行方式; (l) 处理; (m) 输入输出; (n) 连接; (o) 换页连接; (p) 控制流

盒图

出于要有一种不允许违背结构程序设计精神的图形工具的考虑,Nassi和Shneiderman提出了盒图,又称为N-S图。

图给出了结构化控制结构的盒图表示,也给出了调用子程序的盒图表示方法。其中基本符号(a) 顺序; (b) IF_THEN_ELSE型分支; (c) CASE型多分支; (d) 循环; (e) 调用子程序A

PAD 图

PAD是问题分析图(problem analysis diagram)的英文缩写,用二维树形结构的图来表示程序的控制流。

基本符号(a)顺序(先执行P1后执行P2);(b)选择(IF C THEN P1 ELSE P2);(c)CASE型多分支;(d)WHILE型循环(WHILE C DO P);(e)UNTIL型循环(REPEAT P UNTIL C);(f)语句标号;(g)定义

(a) 初始的PAD图; (b) 使用def符号细化处理框P2

判定表

判定表能够清晰地表示复杂的条件组合与应做的动作之间的对应关系。

判定表由4部分组成,

  1. 左上部列出所有条件

  2. 左下部是所有可能做的动作

  3. 右上部是表示各种条件组合的一个矩阵

  4. 右下部是和每种条件组合相对应的动作。

判定表右半部的每一列实质上是一条规则,规定了与特定的条件组合相对应的动作。

判定树

判定树是判定表的变种,它也能清晰地表示复杂的条件组合与应做的动作之间的对应关系。

过程设计语言

过程设计语言(PDL)也称为伪码。是用正文形式表示数据和处理过程的设计工具。

面向数据结构的设计方法

Jackson 图

顺序结构

A由B、C、D 3个元素顺序组成(每个元素只出现一次,出现的次序依次是B、C和D)

选择结构

根据条件A是B或C或D中的某一个(注意,在B、C和D的右上角有小圆圈做标记)

重复结构

A由B出现N次(N≥0)组成(注意,在B的右上角有星号标记)

改进的 Jackson 图

(a) 顺序结构,B、C、D中任一个都不能是选择出现或重复出现的数据元素(即不能是右上角有小圆圈或星号标记的元素);

(b) 选择结构,S右面括号中的数字i是分支条件的编号;

(c) 可选结构,A或者是元素B或者不出现;

(d) 重复结构,循环结束条件的编号为i。

McCabe 方法(流图)

流图

McCabe方法根据程序控制流的复杂程度定量度量程序的复杂程度,这样度量出的结果称为程序的环形复杂度。

流图实质上是“退化了的”程序流程图,描绘程序的控制流程,不表现对数据的具体操作以及分支或循环的具体条件。

  • 一个圆代表一条或多条语句。

  • 一个顺序结构可以合并一个结点。

  • 流图中的箭头线称为边,代表控制流。

  • 在流图中一条边必须终止于一个结点。

image-20211215223730145

由PDL翻译成的流图

image-20211215223750752

复合条件,就是在条件中包含了一个或多个布尔运算符(逻辑OR,AND,NAND,NOR)

计算环形复杂度的方法

  1. 流图中线性无关的区域数等于环形复杂度。

  2. 流图G的环形复杂度V(G)=E-N+2,其中,E是流图中边的条数,N是结点数。

  3. 流图G的环形复杂度V(G)=P+1,其中,P是流图中判定结点的数目。

面向对象方法学

对象模型

对象模型表示静态的、结构化的系统的“数据”性质。它是对模拟客观世界实体的对象以及对象彼此间的关系的映射,描述了系统的静态结构。

对象模型为建立动态模型和功能模型,提供了实质性的框架。

通常,使用UML提供的类图来建立对象模型。

类图

类图描述类及类与类之间的静态关系。类图是一种静态模型,它是创建其他UML图的基础。一个系统可以由多张类图来描述,一个类也可以出现在几张类图中。

定义类

为类命名时应该遵守以下几条准则:

  • 使用标准术语。

  • 使用具有确切含义的名词。

  • 必要时用名词短语作名字。

定义属性

UML描述属性的语法格式如下:

可见性属性名: 类型名=初值{性质串}

  • 属性的可见性(即可访问性)通常有下述3种:公有的(public)、私有的(private)和保护的(protected),分别用加号(+)、减号(-)和井号(#)表示。注意,没有默认的可见性。

  • 属性名和类型名之间用冒号(:)分隔。类型名表示该属性的数据类型,它可以是基本数据类型,也可以是用户自定义的类型。

  • 在创建类的实例时应给其属性赋值,如果给某个属性定义了初值,则该初值可作为创建实例时这个属性的默认值。类型名和初值之间用等号(=)隔开。

  • 用花括号括起来的性质串明确地列出该属性所有可能的取值。枚举类型的属性往往用性质串列出可以选用的枚举值,不同枚举值之间用逗号分隔。也可以用性质串说明属性的其他性质,例如,约束说明{只读}表明该属性是只读属性。

类的属性中还可以有一种能被该类所有对象共享的属性,称为类的作用域属性,也称为类变量。类变量在类图中表示为带下划线的属性。

定义服务

服务也就是操作,UML描述操作的语法格式如下:

可见性 操作名(参数表): 返回值类型{性质串}

  • 操作可见性的定义方法与属性相同。

  • 参数表是用逗号分隔的形式参数的序列。描述一个参数的语法如下:参数名: 类型名=默认值

  • 当操作的调用者未提供实在参数时,该参数就使用默认值。

  • 与属性类似,在类中可定义类作用域操作,在类图中表示为带下划线的操作。这种操作只能存取本类的类作用域属性。

表示关系的符号

  类与类之间通常有关联、泛化(继承)、依赖和细化4种关系。

关联

关联表示两个类的对象之间存在某种语义上的联系。

普通关联

只要在类与类之间存在连接关系就可以用普通关联表示。普通关联的图示符号是连接两个类之间的直线,如下图所示。

关联是双向的,可在每一个方向上为关联起一个名字(也可不起名字)。为避免混淆,在名字前面(或后面)加一个表示关联方向的黑三角。

在表示关联的直线两端可以写上重数(multiplicity),它表示该类有多少个对象与对方的一个对象连接。

如果图中未明确标出关联的重数,则默认重数是1。

关联的角色

在任何关联中都会涉及参与此关联的对象所扮演的角色(即起的作用),在某些情况下显式标明角色名有助于别人理解类图。

如图是一个递归关联(即一个类与它本身有关联关系)的例子。一个人与另一个人结婚,必然一个人扮演丈夫的角色,另一个人扮演妻子的角色。如果没有显式标出角色名,则意味着用类名作为角色名。

限定关联

限定关联通常用在一对多或多对多的关联关系中,可以把模型中的重数从一对多变成一对一,或从多对多简化成多对一。在类图中把限定词放在关联关系末端的一个小方框内。

上图利用限定词“文件名”表示了目录与文件之间的关系,可见,利用限定词把一对多关系简化成了一对一关系。

上图一个受限的关联限定提高了语义精确性,增强了查询能力。限定的语法表明,文件名在其目录内是唯一的。

关联类

为了说明关联的性质,引入一个关联类来记录附加信息。关联中的每个连接与关联类的一个对象相联系。关联类通过一条虚线与关联连接。

关联类与一般的类一样,也有属性、操作和关联。

如图是一个电梯系统的类模型,队列就是电梯控制器类与电梯类的关联关系上的关联类。

一个电梯控制器控制着4台电梯,控制器和电梯之间的实际连接就有4个,每个连接都对应一个队列(对象),每个队列(对象)存储着来自控制器和电梯内部按钮的请求服务信息。

聚集

聚集也称为聚合,是关联的特例。聚集表示类与类之间的关系是整体与部分的关系。使用的“包含”、“组成”、“分为……部分”等字句,意味着存在聚集关系。有共享聚集和组合聚集两种特殊的聚集关系。

共享聚集

如果在聚集关系中处于部分方的对象可同时参与多个处于整体方对象的构成,则该聚集称为共享聚集。下图中,一个课题组包含许多成员,每个成员又可以是另一个课题组的成员,则课题组和成员之间是共享聚集关系。一般聚集和共享聚集的关联关系用空心菱形表示。

组合聚集

如果部分类完全隶属于整体类,部分与整体共存,整体不存在了部分也会随之消失(或失去存在价值了),则该聚集称为组合聚集(简称为组成)。

在屏幕上打开一个窗口,它就由文本框、列表框、按钮和菜单组成,一旦关闭了窗口,各个组成部分也同时消失,窗口和它的组成部分之间存在着组合聚集关系。如图是窗口的组成,组合聚集的组成关系用实心菱形表示。

泛化

UML中的泛化关系就是通常所说的继承关系,它是通用元素和具体元素之间的一种分类关系。具体元素完全拥有通用元素的信息,并且还可以附加一些其他信息。

在UML中,用一端为空心三角形的连线表示泛化关系,三角形的顶角紧挨着通用元素。

泛化关系指出在类与类之间存在“一般--特殊”关系。泛化可进一步划分成普通泛化和受限泛化。

普通泛化

没有具体对象的类称为抽象类。抽象类通常作为父类,用于描述其他类(子类)的公共属性和行为。图示抽象类时,在类名下方附加一个标记值{abstract}。

抽象类通常都具有抽象操作。抽象操作仅用来指定该类的所有子类应具有哪些行为。抽象操作的图示方法与抽象类相似,在操作标记后面跟随一个性质串{abstract}。

与抽象类相反的类是具体类,具体类有自己的对象,并且该类的操作都有具体的实现方法。

受限泛化

给泛化关系附加约束条件,以进一步说明该泛化关系的使用方法或扩充方法,这样的泛化关系称为受限泛化。预定义的约束有4种:多重、不相交、完全和不完全。这些约束都是语义约束。

多重继承指的是,一个子类可以同时多次继承同一个上层基类,如图中的水陆两用类继承了两次交通工具类。

与多重继承相反的是不相交继承,即一个子类不能多次继承同一个基类(这样的基类相当于C++语言中的虚基类)。如果图中没有指定{多重}约束,则是不相交继承,一般的继承都是不相交继承。

完全继承指的是父类的所有子类都已在类图中穷举出来了,图示符号是指定{完全}约束。

不完全继承与完全继承恰好相反,父类的子类并没有都穷举出来,随着对问题理解的深入,可不断补充和维护,这为日后系统的扩充和维护带来很大方便。不完全继承是一般情况下默认的继承关系。

依赖和细化

(1) 依赖关系

依赖关系描述两个模型元素(类、用例等)之间的语义连接关系: 其中一个模型元素是独立的,另一个模型元素不是独立的,它依赖于独立的模型元素,如果独立的模型元素改变了,将影响依赖于它的模型元素。

在UML的类图中,用带箭头的虚线连接有依赖关系的两个类,箭头指向独立的类。在虚线上可以带一个版类标签,具体说明依赖的种类。

 

上图表示一个友元依赖关系,该关系使得B类的操作可以使用A类中私有的或保护的成员。

细化关系

当对同一个事物在不同抽象层次上描述时,这些描述之间具有细化关系。

假设两个模型元素A和B描述同一个事物,它们的区别是抽象层次不同,如果B是在A的基础上的更详细的描述,则称B细化了A,或称A细化成了B。细化的图示符号为由元素B指向元素A的、一端为空心三角形的虚线(注意,不是实线),如下图所示。细化用来协调不同阶段模型之间的关系,表示各个开发阶段不同抽象层次的模型之间的相关性,常常用于跟踪模型的演变。

动态模型

动态模型表示瞬时的、行为化的系统的“控制”性质,它规定了对象模型中的对象的合法变化序列。

通常,用UML提供的状态图来描绘对象的状态、触发状态转换的事件以及对象的行为(对事件的响应)。

每个类的动态行为用一张状态图来描绘,各个类的状态图通过共享事件合并起来,从而构成系统的动态模型。也就是说,动态模型是基于事件共享而互相关联的一组状态图的集合。

事件跟踪图

完整、正确的脚本为建立动态模型奠定了必要的基础。但是,用自然语言书写的脚本往往不够简明,而且有时在阅读时会有二义性。为了有助于建立动态模型,通常在画状态图之前先画出事件跟踪图。为此首先需要进一步明确事件及事件与对象的关系。

事件跟踪图实质上是扩充的脚本,可以认为事件跟踪图是简化的UML顺序图。

在事件跟踪图中,一条竖线代表一个对象,每个事件用一条水平的箭头线表示,箭头方向从事件的发送对象指向接受对象。时间从上向下递增,画在最上面的水平箭头线代表最先发生的事件,画在最下面的水平箭头线所代表的事件最晚发生。箭头线之间的间距并没有具体含义,图中仅用箭头线在垂直方向上的相对位置表示事件发生的先后,并不表示两个事件之间的精确时间差。

状态图

状态图描绘事件与对象状态的关系。当对象接受了一个事件以后,它的下个状态取决于当前状态及所接受的事件。由事件引起的状态改变称为“转换”。如果一个事件并不引起当前状态发生转换,则可忽略这个事件。

功能模型

功能模型表示变化的系统的“功能”性质,它指明系统应该“做什么”,因此更直接地反映了用户对目标系统的需求。

功能模型由一组数据流图组成。建立功能模型有助于软件开发人员更深入地理解问题域,改进和完善自己的设计。

UML提供的用例图是进行需求分析和建立功能模型的强有力工具。在UML中把用用例图建立起来的系统模型称为用例模型。

使用用例模型代替传统的功能说明,往往能够更好地获取用户需求,它所回答的问题是“系统应该为每个(或每类)用户做什么”。

用例模型描述的是外部行为者(actor)所理解的系统功能。用例模型的建立是系统开发者和用户反复讨论的结果,它描述了开发者和用户对需求规格所达成的共识。

用例图

一幅用例图包含的模型元素有系统、行为者、用例及用例之间的关系。如图是自动售货机系统的用例图。图中的方框代表系统,椭圆代表用例(售货、供货和取货款是自动售货机系统的典型用例),线条人代表行为者,它们之间的连线表示关系。

系统

系统被看作是一个提供用例的黑盒子,内部如何工作、用例如何实现对于建立用例模型来说都是不重要的。

代表系统的方框的边线表示系统的边界,用于划定系统的功能范围,定义了系统所具有的功能。描述该系统功能的用例置于方框内,代表外部实体的行为者置于方框外。

用例

一个用例是可以被行为者感受到的、系统的一个完整的功能。在UML中把用例定义成系统完成的一系列动作,动作的结果能被特定的行为者察觉到。这些动作除了完成系统内部的计算与工作外,还包括与一些行为者的通信。用例通过关联与行为者连接,关联指出一个用例与哪些行为者交互,这种交互是双向的。

行为者

行为者是指与系统交互的人或其他系统,它代表外部实体。使用用例并且与系统交互的任何人或物都是行为者。

行为者代表一种角色,而不是某个具体的人或物。一个具体的人可以充当多种不同角色。

在用例图中用直线连接行为者和用例,表示两者之间交换信息,称为通信联系。行为者触发(激活)用例,并与用例交换信息。单个行为者可与多个用例联系;一个用例也可与多个行为者联系。

可以把行为者分成主行为者和副行为者,还可分成主动行为者和被动行为者。

用例之间的关系

UML用例之间主要有扩展和使用两种关系,它们是泛化关系的两种不同形式。

  • 扩展关系向一个用例中添加一些动作后构成了另一个用例,这两个用例之间的关系就是扩展关系,后者继承前者的一些行为,通常把后者称为扩展用例。

  • 使用关系当一个用例使用另一个用例时,这两个用例之间就构成了使用关系。一般说来,如果在若干个用例中有某些相同的动作,则可以把这些相同的动作提取出来单独构成一个用例(称为抽象用例)。这样,当某个用例使用该抽象用例时,就好像这个用例包含了抽象用例中的所有动作。

注意扩展与使用之间的异同: 这两种关系都意味着从几个用例中抽取那些公共的行为并放入一个单独的用例中。通常在描述一般行为的变化时采用扩展关系;在两个或多个用例中出现重复描述又想避免这种重复时,可以采用使用关系。