张 杰,燕雪峰
(南京航空航天大学计算机科学与技术学院,江苏南京 210016)
面向任务的作战系统设计过程是基于任务需求,实现自顶向下的作战系统体系结构设计过程。在需求分析过程中,多个分析人员针对不同的任务进行分析,导致任务模型之间冲突等问题。由于模型的不完整性以及多样性,特别是动态需求模型和功能需求模型,使冲突很难被发现。目前很多学者都对模型一致性技术进行了研究,文献[1]中提出通过SPIN工具来检测顺序图和状态图的一致性,SPIN是一个模拟有限状态并发系统的模型检测工具,以协议/过程语言Promela描述的系统模型与待验证的性质为输入,在找出语法错误的基础上,模拟系统的交互执行;提出用LTL(线性时代逻辑)来描述系统的性质,需要一定的数学基础,而且模型必须转换成 Promela。文献[2]提出基于Büchi自动机理论对状态图和顺序图进行一致性验证的方法,把状态图转换成Büchi自动机As,顺序图转换成多个LTL公式,再把多个LTL公式转换成Büchi自动机集合{Af1,Af2,…,Afn},通过判断 As与自动机集合的乘积是否为空来判断两者是否一致,但该方法的检测结果不能通过直观展示出来。文献[3]中提出基于图转换理论,通过AGG工具静态分析检测用例模型之间的潜在冲突和依赖,AGG是一个对属性图文法进行编辑、分析和推理的可视化工具,对图变换规则进行临界对分析(Critical Pair Analysis)得到规则间潜在的冲突、依赖关系,但检测出的依赖需进一步处理。文中针对作战系统任务模型提出基于AGGCT(Attributed Graph Grammar-based Consistency Checking)的检测方法:把作战系统模型转换成属性图文法,再用AGG工具检测功能模型间的冲突和依赖,并提出循环依赖和错误依赖检测算法对依赖进行进一步处理。
作战系统模型由作战需求视图和UML子图组成。作战需求视图中包含使命和任务两种建模元素。使命确定系统的设计目的和范围,需要多个不同的任务协同完成。任务的动态需求用活动图建模,静态需求用类图建模,功能需求用自然语言对事件的前置和后置条件进行建模。由于自然语言无法形式化,文中提出用对象图来描述功能需求,把动态需求和静态需求结合。对象图中对象是静态需求中类的实例。
以作战系统中护航使命模型为例,潜艇为完成护航使命需要不断侦察是否有敌方目标出现;如果出现敌方潜艇,需要发射鱼雷攻击,所以把护航使命分解成侦察和雷攻击两个任务。
静态需求模型:图1是护航使命的类图。一个潜艇(Submarine)有多部声纳设备(Sonar),同时装载了多个鱼雷(Torpedo),需要一个鱼雷发控装置(Torpedo Fire Control)来控制鱼雷。声纳(Sonar)可以同时探测多匹目标,假定目标为敌方潜艇(Enemy Submarine),检测到目标后发射鱼雷攻击目标。由于在需求阶段,图1中的类没有添加方法,图2是类图的一个实例图。
动态需求模型:图3是护航的作战需求视图以及任务的活动图。潜艇用声纳来侦察,侦察任务首先需要声纳开机(start Up Sonar),然后探测目标(detect),如果目标有威胁,攻击目标(attack)。鱼雷攻击任务活动图包括鱼雷发控装置开机(Startup Torpedo Fire Control)、发射鱼雷(shoot)和设置目标位置(set Target)。
功能需求模型:功能需求用对象图对事件前置和后置条件进行建模。在任务模型中,事件指动态需求中的活动(actions)。侦察任务和鱼雷攻击任务的活动图中事件的前置后置条件分别如图4和图5所示,对象图中每个对象都是静态需求UML类图的实例,例如:在图4声纳开机(startUpSonar)功能需求中对象Submarine是图1中类Submarine的实例。
由于多个需求分析人员分析不同的任务需求,导致模型中存在语义上的重叠,在多个任务协作完成使命的过程中产生错误。需求模型不一致将导致设计中的错误,事后修改代价非常高;如果错误未被发现则会影响系统的可靠性和健壮性。上例中侦察任务和鱼雷攻击任务的功能需求之间存在语义上的重叠,攻击目标(attack)和发射鱼雷(shoot)都删除了Torpedo。由于两个任务协同完成护航使命,所有任务的活动必须依次执行。但由于语义上的重叠导致攻击目标(attack)和发射鱼雷(shoot)无法依次执行,所以功能模型之间存在冲突。
属性图文法[4]既有直观的图形符号又有较成熟的形式化理论,基于规则的图转换可以有效地描述任务的功能需求,所以把作战系统模型的UML子图转换成属性图文法并形式化检测功能需求之间的冲突和依赖。
2.1.1 UML类图转换成类型图
定义1 一个类图模型是一个五元组C=(Cn,Cp,Co,Cr,Cm),其中,Cn表示类名;Cp表示类属性;Co表示类的操作;Cr表示类之间的关系;Cm多重性。文中讨论的类图是处于需求阶段,只考虑类图的静态特性,由于类的操作属于动态性的知识,不予考虑。
定义2 一个类型图模型是一个四元组TG=(TGn,TGp,TGr,TGm),其中 TGn表示图的名称,TGp表示图的属性,TGr表示图的关系,TGm表示多重性。
显然,很容易把类图转换成属性图,由于不考虑类的操作,类图中的Cn,Cp,Cr,Cm可以直接转换成类型图中的 TGn,TGp,TGr,TGm。类之间的关系 Cr有联系(Association)和泛化(Generalization)等。类型图之间的关系TGr有边(Edge)和继承(Extend)两种。类图中的泛化关系可以之间转换成类型图中的继承。
在大多数情况下,类图中两个类之间的联系是二元的,而且,聚集和复合总是二元联系。因此,文中只考虑二元联系。二元联系有一个联系名和两个联系端。每个联系端有一个角色名和一个多重性约束,一个描述导航性的属性和一个描述关系类型的属性。多重性约束描述的非负整数的范围表示该位置上可以有多少个对象,并且限制了一端的一个对象可以和另一端的多少个对象有联系。类型图中的边也是用来表示两个类型图之间的两个类型图可以相互拥有的对象的数目,所以类图中的联系可以直接转换成类型图中的边。
2.1.2 UML对象图转换成规则
定义3 UML对象图是一个二元组G={N,E}。N为节点n的有限集;E为边e的有限集;节点n及边e都用对象表示。
在上文中已经介绍了,活动图的前置后置条件用UML对象图来描述,且UML对象图中的对象都是UML类图中类的实例。在属性图文法中,规则的前置后置条件中的属性图都是类型图的实例,可以直接把UML对象图中的对象转换成规则前置或者后置条件中的实例。UML对象图中的边可以转换成规则前置或者后置条件中的边,所以UML对象图可以转换成规则的条件后置条件。
利用上述转换方法,静态需求中UML类图对应属性图文法中的类型图。UML类图的实例图作为属性图文法的开始图,开始图代表图转换的起点。功能需求转换成属性图文法中的图转换规则集,功能需求前置条件对象图对应规则的左部图,后置条件对象图对应规则的右部图。由于模型中没有对功能需求限制执行条件,所以属性图文法中约束集为空。本文用AGG工具来分析任务模型转化的属性图文法,得到功能需求之间的冲突和依赖。
两个图转换规则之间有依赖关系是指一个规则的执行必须以另一个规则的执行为前提条件,AGG工具检测出所有功能需求之间的依赖关系,但没有进行详细分析。循环依赖是指依赖关系中出现环,错误依赖表示功能需求之间依赖关系与动态需求中活动图的执行流程不一致。循环依赖或错误依赖一般是设计中的错误,所以需要对依赖关系进行验证。
该算法对使命中功能需求之间的依赖关系深度搜索,同时加入栈来记录搜索路径,如果在搜索中出现栈中已经存在的功能需求,说明找到环,同时输出环中所有元素。假设有3个功能需求A、B、C,A依赖B,B依赖C,C依赖A,三者的依赖关系形成一个环。首先对A的依赖关系进行深度搜索,通过A的依赖关系找到B,再对B进行搜索,找到C,这时栈中保存的是A、B、C,在对C进行搜索的过程中找到A,因为A已经存在栈中,所以找到一个环,输出环中元素A、B、C、A。相关定义如下:(1)功能需求 FunctionRequirement=<name,dependencs>,name是名称,dependeces是该功能需求依赖关系数组。(2)任务Task=<name,functionRequirements>,name表示任务的名称,functionRequirements是任务的功能需求数组。(3)使命Mission=<name,tasks>,name表示使命的名称,tasks是完成使命的所有任务。(4)frs数组记录使命中所有功能需求,用visited数组来表示功能需求是否被遍历过,初始化为false。(5)栈stack用来记录遍历路径,算法调用之前栈为空;top表示栈顶的位置,初始化为-1。(6)count用来记录环的个数,初始化为0。
图6 循环依赖检测算法
假设活动action1的功能需求依赖活动action2的功能需求,且action1和action2在同个活动图中,那么action2必须在action1之前执行,即活动图中必须存在action2→action1或者action2→…→action1执行流程,否则该依赖关系是一个错误依赖。UML活动图中主要的建模元素是活动(Action)、判断(Decision)和转换(Transition),因此判断活动图的执行流程时节点只考虑这3个元素。首先需要遍历活动图中的所有模型元素,找到所有的活动和判断节点。然后从action2开始对活动图进行深度搜索通过单步转换(Transition)到达的活动或判断节点,如果在搜索的过程中发现action1,说明活动图中有该活动流,否则继续至结束。相关定义如下:(1)功能需求FunctionRequirement=<name,dependencs>,name表示名称,dependeces是该功能需求依赖关系数组。(2)任务Task=<name,functionRequirements>,name表示任务的名称,functionRequirements是任务功能需求数组。(3)actions数组记录活动图中所有的活动,decisions记录活动图中所有的判断。(4)isActionVisited数组用于记录活动图中所有的活动是否被搜索过,与actions数组对应;isDecisionVisited数组用来记录活动图中所有的判断是否被搜索过,与decisions数组对应。
图7 错误依赖检测算法
作战系统需求工具中用AGGCT一致性检测方法来保证建模的正确性。基于AGGCT一致性检测系统的输入是有领域模型和UML模型组成的作战系统模型,检测结果会输出所有的冲突依赖关系、错误依赖和循环依赖。检测系统的类图如图8所示,其主要职责如表1所示。
图8 基于AGGCT一致性检测系统的类图
表1 基于AGGCT一致性检测系统中类的主要职责
用该系统检测第一章中的护航使命模型,图8是AGG检测出shoot和attack都删除了torpedo引起的冲突。由于协同完成护航使命,只能由其中一个执行删除操作。所以修改了attack活动的功能需求,删除torpedo操作只由shoot活动来执行,消除了冲突。
图9 shoot和attack之间的冲突
AGG工具把所有任务的功能需求之间的依赖关系用矩阵显示,如图10所示,记每个功能需求为pi,如果pi依赖pj,则表格第j行第i列的数字>0,如果没有依赖关系,则等于0。例如:attack依赖于detect,那么第2行第3列上的数字约为0。功能需求不能依赖本身,所以矩阵对角线的位置并没有计算。
图10 修改之后的攻击目标(attack)功能需求
一致性检测系统对图10中所有的依赖关系进行检测,发现依赖关系中没有循环依赖,shoot对setTarget的依赖关系是错误依赖。在图3中,鱼雷攻击任务的活动图中发射鱼雷(shoot)发生在设置目标位置(setTarget)之前,而功能需求中shoot对setTarget的依赖则要求设置目标位置(setTarget)必须在发射鱼雷(shoot)之前执行。所以,修改鱼雷攻击任务的活动图,把设置目标位置活动(setTarget)放在发射鱼雷活动(shoot)之前,活动的执行流程与依赖关系一致,消除了错误依赖。
图11 功能需求之间的依赖关系
模型一致性以及验证一直是软件工程领域内研究的热点,本文考虑作战系统中不同需求分析人员针对不同的任务进行分析的特点,提出一种基于图文法形式化检测任务模型一致性的方法,把作战系统模型转换成属性图文法并检测功能需求间的冲突和依赖,同时验证了依赖关系中是否存在循环依赖和错误依赖。提出了相应的检测算法,循环依赖检测算法通过深度优先搜索找到依赖关系中的环,同时输出环中的所有依赖关系;错误依赖检测算法对活动图进行深度优先搜索,检测功能模型的依赖关系与动态模型的执行流程是否一致。任务可能还含有子任务,子任务是否可以继承父任务的约束关系,以及如何检测子任务间的冲突和依赖,可以作为下一步的研究方向。
[1]陈卉,窦万峰.UML顺序图与状态图的一致性检查[J].计算机工程,2008,34(18):62 -64.
[2]张自强.基于自动机理论的UML模型一致性研究[D].兰州:兰州大学,2009.
[3]JAN H H,REIKO H,GABI T.Detection of conflicting fuctional requirements in a use case - driven approach[J].SoftWare Enginneering,2002:105 -115.
[4]邢阳,谢德平,马晓星,等.一种图文法制导的软件体系结构开发环境Artemis-GADE[J].计算机研究与发展,2010,47(7):1166 -1173.
[5]韩秀清,曾晓勤,邹阳,等.图文法综述[J].计算机科学,2008,35(8):10 -16.
[6]刘辉,麻志毅,邵维忠.一种基于图转换的模型重构描述语言[J].软件学报,2009,20(8):2087-2101.