需求工程:基础、原理和技术5 |
波尔(Klaus Pohl) |
计算机科学丛书 |
13:面相方案的需求基础、14:面向方案需求的文档化、16:需求文档基础 |
第13章 面向方案的需求基础
面向方案的需求定义了系统需要实现的属性和特征。
面向方案的需求应当描述单一的统一 视图,并且不包含冲突。
在系统开发开始以前,所有冲突都应该得到解决。面向方案的需求与目标和场景一起构成了系统实现的基础。
13.1解决方案的3种视图
软件密集型系统的需求应当以一种便于系统开发的方式进行定义。需求应该以一种支持软件解决方案开发的方式进行定义。
❑数据视图:数据视图关注于定义需要由软件密集型系统管理的数据/信息。数据视图考虑并定义了数据的静态方面,包括实体、实体之间的关系、属性、与系统相关的属性类型等。数据视图并不考虑对于数据的操纵(数据的动态方面)。
❑功能视图:功能视图通常定义了系统需要提供的处理过程(功能)、每一个处理过程中对于数据的操纵、处理过程之间的输入输出关系(信息流)。通常,数据流图可以用来描述系统的功能视图。
❑行为视图:行为视图关注于定义系统的总体行为。行为视图定义了系统所接收的外部激励、系统的响应,以及二者之间的关系等。行为视图还定义了系统可能处于的状态以及这些状态之间所允许的变迁关系。
三种视图之间的关系
这3种视图的建模语言中所定义的建模元素刻画的是所表示的领域(论域)中相同的主体。
❑数据和功能视图中的系统数据规约:系统的数据需求在数据视图中定义,数据也是功能视图中所定义的需求的主题。
❑功能与行为视图中的系统功能规约:功能规约(如数据流模型)用来定义系统需要提供的功能(处理过程)。描述的行为规约通常定义了相关功能应当在何时被执行。
13.2 面向方案的需求、目标和场景
13.2.1 主要区别
面向方案的需求、目标和场景这3种制品类型的5种典型特性基础上分析三者之间的主要区别。
❑共识:对于目标的全面的共识往往是不存在的。并非所有涉众都必须对所定义的场景达成一致。相反,系统中定义的面向方案的需求应得到所有涉众的一致同意。
❑完整性:目标陈述了所期望的、根本性的系统属性,但并未定义每个属性的细节。场景通常并未定义系统和上下文之间所有可能的交互序列,它们定义了满足所定义的目标的典型交互序列。与之相反,为一个系统所定义的面向方案的需求应当尽可能完整。
❑冲突:目标通常包含冲突,场景之间也可能存在冲突。而为系统定义的面向方案的需求之中则不应当存在任何冲突。
❑详细程度:与目标和场景相反,面向方案的需求应当以一种便于系统明确、无二义地实现的方式详细定义。与目标和场景相比,面向方案的需求因此包括更多的细节。
❑期望的解决方案:目标是以一种与所期望的解决方案相互独立(与解决方案无关)的方式定义的。相反,面向方案的需求通常部分描述了所期望的解决方案,给出了解决方案空间的严格约束。
目标、场景与面向方案的需求的粗粒度特性比较
13.2.2 主要联系
目标和场景为面向方案的需求的抽取和确认提供了很好的基础。
面向方案的需求与目标/场景之间的关系
❑面向方案的需求的抽取:面向方案的需求可以从场景(部分从目标)中进行抽取,识别必须满足哪些特定的面向方案的需求以实现这些场景。
❑面向方案的需求的精化:
❑面向方案的需求的确认:涉众还可以检查面向方案的需求是否与所定义的场景相冲突。
❑新的目标与场景的识别:可能导致新的系统应当满足的场景和/或目标(直接来自涉众或其他来源)的识别。
第14章 面向方案需求的文档化
使用自然语言描述面向方案的需求
如果使用自然语言描述面向方案的需求,那么数据、功能、行为等3种视图通常是混合在一起的。
使用模型描述面向方案的需求
与自然语言规约相比,基于模型的需求有助于避免将上述3种视图混合在一起。
❑数据建模语言用来描述数据方面。
❑行为建模语言用来描述行为方面。
❑功能建模语言用来描述功能方面。
14.1数据视图中的需求描述
数据模型描述了数据方面,例如与系统相关的实体以及实体关系和属性。通常,实体、属性 和关系可以通过考虑主体刻面进行识别。
数据模型是在类型层次(或模型层次)上进行定义的,即描述了实体类型和关系类型。
常见的建模语言
数据建模方面主要使用的方法是实体-关系(ER)模型。
14.1.1 增强的实体-关系模型
实体类型
实体类型(经常被称作实体)表示一组具有相似属性的实体。其中,实体类型是对具体实体(即实例)的抽象。
关系类型
关系类型(通常也被称作关系)与两个或多个实体类型相关。它代表一组相似的关系实例,这些关系实例将各个类型的实体关联起来并且与待开发的系统相关。
属性
属性定义了与系统相关的性质。通过为实体类型定义属性,我们可以为该类型中的每一个实体定义属性。属性可以是单值的,也可以是多值的。属性也可以由其他属性组合而成。
基数约束
基数约束限制了可以参加一个所定义的关系类型中的实体的个数。基数约束可以在一个关系类型的每一端上进行定义。标识(max、min)用来定义基数约束。
提示14-1:创建ER模型
作为实体类型描述:
❑如果系统必须发送、接收或持久储存某种类型对象的信息,则将该对象类型建模成实 体类型。
作为属性描述:
❑实体类型中与系统相关的信息使用属性描述。
实体类型vs.属性:
❑实体具有自身的标识。而一个属性只有作为某些实体(或关系)的特性时才有意义。
❑如果某个实体类型E₁只有一个属性并且只与一个其他实体类型E₂相关联,则应该考 虑将E₁建模为E₂的一个属性。
属性vs.关系:
❑如果某个实体类型E₁的一个属性是对另一个实体类型E₂的引用,则应该考虑将该属 性建模为一个关系(类型)。如果一个为E₂定义的属性是对E₁的引用,也应如此 处理。
实体类型vs.关系:
❑当一个实体具有自身的标识时,关系通过参与关系的实体那里获得标识信息。
14.1.2 类图
UML2类图被用于在不同抽象层次上描述系统。类图在需求工程以及设计和实现过程中创建和精化。类图用来描述系统的静态视图。
类
类描述具有相似结构、相似行为和相似关系的一组(物质或非物质)对象。
类通常表示为分隔成3部分的矩形。矩形中的第一个部分定义了类的名称。第二部分定义了类的属性。第三部分定义了类提供的操作。类定义的详细程度取决于建模的目的。
属性
类属性在类的属性部分采用文本行的方式进行定义。定义属性时仅有属性名是必需的。
❑类型:属性类型由分类符(如类或数据类型)来指定。类型限定了可以指派给该属性的值。
❑重数(multiplicity):重数由上界和下界组成,表示可以指派给属性的值的数量。
❑属性字符串:属性字符串的例子包括{ordered}、{unique}、{read only}等。
关系
关系用来表示类之间的相互关联。类 C₁和类C₂之间的关系A表示C₁和C₂的 对象之间的一组关联。
类图中的关系可以标注一个关系名。在关系的每一端上还可以为附在该端上的类定义角色、重数和属性字符串。
❑角色:角色名定义了这个类在关系中所扮演的角色。
❑重数:重数定义了这个关系端上的类可以有多少个实例参与到该关系中。
❑属性字符串:针对关系的某一未定义的属性字符串与定义属性一样。
关系的图形化表示
聚合和组合
有两种特殊的关系:聚合(aggregation)和组合(composition)。描述的是整体和部分关系。
组合表示一种比聚合更强的整体部分关系。在组合关系中,每一部分只有一个所有者,即只能是一个组合体的部分。通常,组合体的各个部分无法脱离组合体存在。如果组合体被销毁,那么它的所有部分都要销毁。
泛化
泛化关系将子类与父类关联起来。子类的实例是父类的间接实例。一个子类对其父类具有可替换性。子类继承父类的属性、操作和关系,同时可以定义新的属性、操作和关系。必要时,子类还可以覆盖所继承的属性、操作和关系。
抽象类
一个抽象类没有直接实例。只有其(非抽象)子类才能有直接实例。
抽象类定义和普通类相似,只是类名用斜体书写。
对象
对象是类的实例。对于类定义的每一个属性都有具体的值。对象通过关系与其他对象联系在一起。
类图通常并不会对对象进行建模。
UML提供了对象图来建模对象以及对象之间的关系。对象图可以用来描述系统在某个特定时间点上的对象以及对象之间关系,即一种快照。对象图可以被视为类图的实例化。
提示14-2:创建类图
类:
❑类名应该是一个名词;
❑类名应该是唯一、易理解的。
关系:
❑关系名应该是一个动词;
❑在自反性关系(即一个类与自身的关系)中,角色名必须被标注;
❑如果两个类是整体-部分关系,那么应该使用聚合或者组合而不是一般的关系。如果一个部分同时只能属于最多一个组合体,并且该组合体负责管理这个部分(如创建和销毁),那么应该使用组合关系(实菱形)。当一个部分可以同时属于多个聚合体,那么应该使用聚合关系。
属性:
❑属性名应该是一个名词;
❑属性名应该是唯一的;
❑如果不清楚属性应该属于类还是类的关系,那么应该检查当关系被移除后该属性是否仍然存在于类的每个对象中。如果存在,那么属性属于类,反之属于关系。
类vs.属性:
❑类的对象独立于其他对象存在。相反,仅当属性所关联的对象存在时,该属性才存在。
14.2 功能视图中的需求描述
功能视图通过使用功能性模型描述面向方案的需求。系统的功能模型按照功能以及功能与数据存储之间的数据流来描述系统需求。
功能建模语言
面向功能的分析方法主要包括:
❑结构化分析(SA);
❑结构化分析与设计技术(SADT);
❑结构化系统分析;
❑本质系统分析;
❑现代结构化分析。
14.2.1 数据流模型
一个数据流模型由一组数据流图、一个数据字典和一个简要规约组成。
流程(功能)
一个流程或者功能表示系统应该提供或者完成的任务或者活动。
源/接收端
源和接收端是通过数据流与系统通信的外部对象(如人、一组人、部门、组织、其他 系统)。
源端将数据传送给系统或者系统中定义的流程。接收端从系统或者系统中定义的流程那里接收数据。
数据存储
数据存储定义了一个数据的存储库。数据存储持久化地记录系统数据。系统的流程可以访问数据存储中的数据(即数据能够被读写)。
数据流
数据流描述了结构已知的信息数据包的传输。数据流可以定义一系列物质和/或非物质对象的流。
数据流可以被定义为流程之间、流程与文件之间,以及流程与源或接收端之间。
数据字典
数据字典包含数据流、数据存储及其组成成分的定义。数据字典是和数据流图同时定义的。
没有数据字典中的数据定义,系统的数据流图就不是良定义的,因此也无法被无二义地解读。
数据流图中的数据流和数据存储都必须在数据字典中进行定义。
简要规约
简要规约(Mini-Spec)中包含对于流程的简要描述。DFD中的每一个流程要么在简要规约中进行定义。
简要规约简要描述了流程如何在其输入的基础上产生输出。简要规约不会定义相应的算法而只是定义了一个策略。
简要规约中涉及的数据元素必须在数据字典中进行定义。
表14-1数据字典中的数据定义表示法 | ||
表示法 | 含义 | 解 释 |
= | 等于 | 通过其他数据元素进行数据元素定义 |
士 | 和 | 数据元素与其他数据元素进行组合 |
x{…}y | 迭代 | {…}中的元素重复x~y次;x和y可选 |
[…|…|…] | 或 | 多个选项中的一个 |
(…) | 可选 | (…)中元素的0次或1次迭代 |
“…” | 原子数据 | 原子数据元素,即不是由其他数据元素定义的元素 |
.* | 注释 | 数据元素的文本解释 |
层次化分解
DFD中定义的流程可以被精化为另一个DFD。
最高层上的DFD一般用大约5~7个流程和数据存储来定义系统的总体功能。
第二层(1层图)包含多个DFD,每个1层的DFD都对0层中的某一个流程进行精化。
可以为每个流程定义不同的分解层数。
在分解层次的叶子上定义的流程,即不再被进一步精化的流程,被称作功能原子。
平衡规则
平衡规则保证一组层次化DFD图中父子DFD之间的一致性。
假设流 程P₁在父数据流图D₁中定义,子数据流图D₂对P₁进行了精化。此时,D₂的所有输入数据流必须和P₁的输入数据流相同,并且D₂的输出数据流也必须和P₁的输出数据流相同。
提示14-3:创建数据流图
DFD的规模:
❑注意保持DFD的可阅读性。单个DFD不能包含多于7±2个流程/数据存储。
数据流:
❑每个数据流都应该有一个表示该数据流所携带数据种类的名字。然而,该规则有一个例外。为了更好的可读性,如果数据流定义了对某数据存储的读或写访问,而其该数据存储的名字已经充分说明了该数据流,那么数据流的名字可以省略。
❑数据流名称应该是易理解的,即它应该能描述数据流信息的特征。
❑数据流名还应该能指明信息的关键属性(例如,应该使用“新路径”、“可选路径”或者类似的说法来表示数据流而不是仅仅使用“路径”)。
❑如果发现很难为数据流取名,那么所考虑的对象可能并不是数据流。此时应该考虑重新构造系统模型。重新构造通常会能够更容易地找到正确的数据流(和流程)名字。
❑如果由流程P₁到P₂的两个不同数据流所携带的数据包可以被视为一个组合,那么应该将这些数据流建模为单个数据流。
❑如果一个流程修改数据存储中已有的数据,那么必须先读取该数据。然而,如果该流程的主要任务是修改数据,那么只需要建模一个由流程到数据存储的数据流,而读取访问则不必表示。这种做法降低了复杂性并有助于识别流程的主要任务。
❑如果对数据存储的读和写访问同样重要,那么应该将这两个数据流建模为一个双向的数据流(带有双向箭头的数据流),但前提是两个方向上流动的信息的类型相同。
流程:
❑流程的名字应该包含一个动词和一个名词。
❑流程名应该是易理解的,即名字应该描述流程的处理内容。
❑如果难以为流程命名,那么应该考虑重新构造系统模型,这通常能够使流程命名更加容易。
源和接收端:
❑源和接收端应该在最高层上定义。如果需要,源和接收端还可以在较低层次上进行精化。
注意避免以下错误:
❑避免使用无意义的数据流名称,如“数据”或“信息”。
❑避免在数据流中隐含定义控制流,如“获取下一条记录”。
❑避免将数据流定义为激活事件,如(针对一个流程)“开始”。
❑避免使用无意义的流程名称,如“处理数据”。
❑避免定义只有输入数据(即没有输出数据)或者只有输出数据(即仅产生输出)的流程。
❑避免定义输入和输出相同的流程(即未作任何处理的流程)。
❑避免定义只发出数据流或者只接收数据流的数据存储。
❑避免定义数据存储之间的数据流。
❑避免定义源和接收端之间的数据流。
14.2.2 本质模型
本质系统分析是对结构化分析的改进,其主要思想是区分真实的(本质)需求和虚假的需求。
本质(真实)需求描述了无论使用什么技术来实现系统,系统都必须提供的属性。
虚假需求是与实现技术相关的需求,定义了系统的对应物。
**注:本质模型图和数据流模型,几乎采用同样的图形表示方法。
包括,基本活动、保存活动=流程功能。本质存储=存储。
基本活动
基本活动是作为系统存在的基本依据的活动。
每一个基本活动都会创建提供系统输出的数据流,即从系统流向系统上下文(源和接收端)的数据流。
保存活动
保存(custodial)活动通过获取并更新系统执行基本活动所需的数据来创建和维护系统的本质存储。
保存活动创建流向本质存储的数据流。
混合本质活动
许多本质活动既是基本活动又是保存活动,即它们通过数据流向环境/上下文提供输出,同时通过流向本质存储的数据流更新本质数据。
本质存储
在本质系统分析中假设在系统边界内存在着完美的技术。
如果从上下文中获得的信息(数据)不仅是接收该信息的流程需要,而且还要留待系统稍后使用,那么该信息必须被存储在系统的本质存储中。
本质存储中保存着从上下文那里获得的,且是基本活动所需要的信息
提示14-4:本质建模的原则
技术中立原则:
❑本质模型不应包含任何有关系统实现的信息。
完美的内部技术原则:
❑系统内的技术是完美的,然而系统上下文中的技术是不完美的。
最小本质模型原则:
❑当有多种方式来规约本质需求时,选择最简单的那个。
复杂性安排规则:
❑不应该存在过于复杂以至于让读者无法轻易理解的模型元素。
14.3 行为视图中的需求描述
行为模型通常用来描述系统的反应性行为,主要使用以下这些概念来定义系统的动态行为:
❑状态:状态定义了一个时间段,在该时间段内系统以某种特定方式运转或者等待某种已定义的、能够触发状态转换的事件的发生。
❑事件:事件是指现实世界中的一种离散性的事件。事件的发生是瞬时的,即认为事件的发生是不消耗时间的。有两类事件:外部事件和时间性事件。外部事件是发生在系统环境中并期待系统做出回应的的事件。时间性事件表示到达了特定时刻,该时刻将触发系统执行某些动作。
❑状态转换:事件触发状态转换。状态转换描述了系统状态的变化,即系统由当前状态变化到另一个状态。
14.3.4 状态图
状态图建模语言。状态图通过一系列简化系统行为建模的改进对有限自动机进行了扩展。
状态图所提供的几个主要改进:
❑为状态和转换定义动作;
❑定义带条件的转换;
❑状态的层次精化;
❑建模并行行为。
为状态和转换定义动作
❑当执行一个状态转换时(Mealy型);
❑进入一个特定状态时(Moore型);
❑处于该状态中的时候,或者;
❑离开一个状态时。
带动作的状态和转换的图形化表示
带条件的转换
状态图支持带条件的状态转换。为状态转换增加条件后,该转换只有在相应事件发生并且所指定的条件满足时,转换才会发生。
条件定义在触发转换的事件后面的括号中。
层次精化
状态图支持将一个状态精化为多个子状态,或者反过来将多个状态“聚合”为一个父状态。
状态图支持层次化的状态定义。
一个父状态对系统的部分行为进行了封装,即子状态所定义的行为封装在父状态中。
并行
一个父状态可以被分解为若干并行组件。若系统进入一个定义了并行组件的父状态,系统将同时进入所有组件。
并行组件还可以被进一步精化,即可以为每个并行组件定义子状态和转换。
父状态的多个并行组件用虚线分隔开。
提示14-5:创建状态图的规则
识别相关状态:
❑寻找系统除了等待事件发生之外不做任何事情的状态。
❑寻找表示持续执行(直到自我终止或者被更高优先级事件中断)的行为的状态。
识别相关事件:
❑寻找两类相关事件:外部事件和时间性事件。如果一个事件要求系统进行响应(即需要 状态转换或执行某种动作或兼而有之),那么该事件是相关事件。
建立层次结构:
❑将多个状态聚合成一个父状态,以表示这些状态在行为上所具有的共性,例如当特定 事件发生时转换到同一个目标状态。
14.3.5状态机图
UML2中的状态机图基于状态图建模语言。状态机图的关键建模元素与状态图相兼容。
状态和转换
UML2状态机图中定义的状态与状态图中所定义的状态一样,都表示一个时间段,在该时间端内系统表现出特定的行为并且等待某种事件的发生。
状态机开始执行时将首先进入状态机的缺省状态,该缺省状态通过状态机图的初始状态来指明。初始状态并不是真正的系统状态,而是状态机的一个控制元素。因此,初始状态也被称作“初始伪状态”。初始伪状态具有唯一的、指向状态机缺省状态的状态转换。
状态机图中的转换定义了由一种状态到另一种状态的改变。转换由事件的发生所触发。
转换还受转换条件的约束。如果一个转换定义了转换条件,那么当触发事件发生时只有该条件同时满足时该转换才会执行。
在UML2中,以下事件类型可以被用来定义转换的触发事件:
❑变化事件:当一个用布尔表达式表达的条件由于布尔表达式中某个元素值的变化而由假变为真时,那么一个变化事件就发生了。变化事件与转换条件的区别在于,转换条件只会当转换的触发事件发生时判断一次,而变化事件的布尔条件值则会被持续计算和评估。
❑时间事件:当某个时间表达式被满足时,一个时间事件就发生了。可以使用绝对时间或者相对时间。
终结状态表示状态机完成了执行过程。终结状态不允许存在对外的事件触发的转换,否则就不是终结状态而是普通状态。
状态和转换的表示法
活动
与状态图中的动作相似,状态机图中还可以定义系统在状态转换时、进入状态时、离开状态时、处于状态中所要执行的活动。
完成转换是指没有触发事件的转换。完成转换将在源状态中的所有活动执行完毕后立即被启动(或激活)。
如果完成转换定义了转换条件,那么该转换仅当转换条件为真时才会被执行。
可以为一个状态定义多个具有不同转换条件的完成转换。
通过定义状态的内部转换可以在不改变状态的情况下触发活动。如果一个内部转换的触发事件在系统处于该状态时发生,那么为该转换定义的活动将被执行并且不需要离开并重新进入该状态。
层次精化
和状态图一样,状态机图中定义的每个状态都可以被分解为一组子状态。
如果包含正交区域的父状态中的每个区域都到达终结状态,那么该父状态的终止转换将被触发。
子机状态
UML2状态机图的子机状态是指引用了另一个状态机的状态。
进入子机状态等价于进入了子机所引用的状态机的缺省状态。如果到达子机所引用状态机的终结状态,则子机状态的终止转换被激活。子机状态定义使得可以在状态机定义中复用其他状态机。