基于FSM的UML模型与代码一致性动态检测

2022-01-11 05:06宋慧娜
关键词:源代码调用一致性

王 雷,张 帅,宋慧娜

(1.延安大学 数学与计算机科学学院;2.陕西省能源大数据智能处理省市共建重点实验室; 3.延安大学 上海文思海辉联合实验室(大数据应用开发方向),陕西 延安 716000)

UML[1]是目前面向对象程序设计中使用最广泛的建模技术。在基于UML的软件开发过程中,应用程序员需要根据UML面向对象分析与设计结果来编写程序。然而,在实际的编程过程中,往往会因为应用程序员的个人水平、软件设计师和应用程序员存在理解偏差以及赶进度和节约成本等各种各样的原因导致UML模型与编写的源代码之间存在不一致。此外,敏捷开发模式已经成为目前软件领域的主流开发方法之一[2]。该开发方法强调可运行的软件胜过宽泛的文档,强调对变更的响应胜过按部就班的遵循计划[3-4]。因此,对于使用敏捷开发方法构建的软件系统,UML模型与源代码的不一致问题更为严重。使用软件工程工具自动检测出UML模型与源代码之间存在的不一致并对存在的不一致进行修改,可以为软件项目,尤其是大型软件项目后期的理解、维护和重构提供便利。近10年来,随着物联网、大数据、云计算、人工智能等前沿技术的兴起,软件系统的规模越来越大,复杂程序越来越高,UML模型与源代码一致性检测的研究就变得越来越有必要。

目前国内外有很多学者致力于UML的各种模型之间一致性检测问题的研究。例如,Ekanayake等[5]提出一种UML类图和顺序图一致性检测方法;Yao等[6]、钱成等[7]、杜杰等[8]研究了基于模型检测的UML顺序图和状态图一致性检测;Chanda等[9]提出一种UML类图、用例图和活动图之间的一致性检测方法;Khai等[10]给出一种基于Prolog的UML类图和顺序图一致性检测方法;Kowal等在文献[11-12]中提出一种基于UML的多层建模方法,并在文献[13]中讨论了不同级别的UML模型的一致性检测;Straeten等[14]提出一种基于描述逻辑(description logic)的UML模型不同版本之间的一致性检测和解决方法;Long等[15]、Chama等[16]探索了由UML模型自动生成一致性代码的方法。这些文献均无法对源代码和UML模型之间的不一致进行检测。

针对UML模型与代码之间的一致性检测的研究还比较少。曾一等[17]通过对Java源代码的词法分析和语法分析获取类的信息及方法调用图(CG,call graph),然后将类的信息以及CG与UML模型进行匹配;Pires等[18]自动生成从UML类图到Java代码的设计测试,这些代码扮演设计测试和实现语言的双重角色;Chavez等[19]试图检查在测试用例上调用Java程序之后生成的状态是否与UML设计类图关联的所有约束一致。这些方法都未通过动态执行源代码来检测UML模型与代码的一致性,因此这些方法无法检测出只有通过动态执行源代码才能发现的不一致。

针对以上问题,提出一种基于图论和FSM的UML模型与源代码一致性检测方法。在之前的研究中[20],已经讨论了基于图论的UML模型(目前只考虑UML类图和顺序图)与源代码一致性静态检测方法,并初步讨论了UML模型与代码一致性动态检测。在此基础上,本文讨论了基于FSM的UML模型与代码一致性动态检测方法。该方法执行源代码并捕获方法调用跟踪,将捕获的方法调用与UML顺序图转换得到的FSM进行匹配,以此来检测动态行为的一致性。实验结果表明,在基于图论的UML模型与代码一致性静态检测的基础上,该方法可以对UML模型与代码的一致性进行动态检测。相对于仅进行静态检测的方法,本文可以检测出更多的不一致,具有更高的检测准确率。

1 基本流程

在前期研究中[20],作者提出一种基于图论和FSM的UML模型与源代码一致性检测方法,基本思路如图1所示。

UML模型与代码的一致性静态检测已经在文献[20]中进行了详细讨论,本文接着进行一致性动态检测以提高检测的精确率。

UML模型与代码一致性动态检测的基本流程是:首先将UML顺序图转换为FSM。然后监视正在分析的程序的函数调用,并将它们与UML顺序图转换得到的FSM进行匹配。若匹配不成功则说明存在不一致,修改源代码直到源代码的动态行为与UML顺序图完全一致。

图1 基于图论和FSM的UML模型与源代码 一致性检测基本思路

2 UML顺序图到FSM的转换

要使用FSM的验证技术对UML顺序图和源代码进行一致性检测,首先需要将UML顺序图转换为FSM模型。UML 2.0序列图有两类基本元素:函数调用和交互片段。下面定义从序列图的两种基本元素到FSM的转换规则(本文借鉴了文献[21]转换方法并对其进行了细化)。

1)函数调用

规则1 对于函数调用,转换为两个状态和他们之间的转移。如图2所示。

图2 函数调用到FSM的转换

其中转移接收的符号由来源于顺序图的变量的连结组成:调用者的类对象(A),调用符号“->”,被调用者的类(B),以及被调用函数m1(后两者用点分隔)。

对于两个顺序的函数调用,将二者分别按照规则1转换,然后将第一个调用的FSM的结束状态与第二个调用的FSM的开始状态合并。如图3所示。

图3 顺序调用到FSM的转换

2)交互片段

规则2 对于可选(optional)调用,转换为两个状态和他们之间的两个转移。其中一个转移接收的符号同普通函数调用,另一个接收空符号ε。如图4所示。

图4 可选调用到FSM的转换

规则3 对于循环(loop),转换为一个开始状态和一个结束状态,再加一个接收空符号的转移。该转移直接从结束状态到开始状态来重复循环。如图5所示。

图5 循环到FSM的转换

规则4 对于若干个供选择的(alternative)调用,转换为两个状态和他们之间的若干个转移。每个转移接收的符号对应一个分支。如图6所示。

图6 供选择的调用到FSM的转换

这里继续以笔者所在实验室研发的UML模型正确性检测工具UML Checker1.0[22]为例来说明UML顺序图到FSM的转换。根据上述转换规则,将文献[20]中图3所示UML顺序图转换为FSM模型,如图7所示(标有箭头的节点表示初始状态,双圈节点表示终结状态)。

3 函数调用与FSM的匹配

将UML顺序图转换为FSM后,就可以监视正在分析的程序的函数调用并将其与转换得到的FSM进行匹配。详细步骤如下:

步骤1 对于每个待检测功能模块,设计合适的测试用例。

步骤2 对于每个测试用例,执行源代码并捕获方法调用跟踪。

步骤3 将捕获到的方法调用跟踪发送到FSM。这里为FSM的状态引入一个令牌(Token)(图7中的黑点)。令牌在FSM中的位置表示FSM当前的状态。从初始状态出发,依次检测是否存在消耗方法调用跟踪中的事件的从当前状态出发的传出转移。事件的调用者和被调用者的类和方法必须匹配转换符号中指定的类和方法。如果匹配成功,那么转移会消耗该事件并将令牌移动到转移的目标状态。

图7 模型导入功能的UML顺序图的FSM表示

步骤4 若方法调用跟踪中的事件全部匹配成功,同时FSM到达终结状态,则说明方法调用跟踪与FSM一致。否则给出不一致说明并手动修改源代码直到方法调用跟踪与FSM完全一致。

继续以UML Checker1.0为例来说明UML顺序图和源代码的动态行为一致性检测。这里为UMLChecker1.0的模型导入功能提供两个测试用例:一个XML格式文件作为正常输入,一个非XML格式文件作为异常输入。导入XML格式文件捕获到的方法调用跟踪如下(只列出前12个方法调用事件和最后一个调用事件):

U2CChckerDlg->CResolve.GetUMLFromXML

CResolve->CResolve.GetClassFromXML

CResolve->CClass.SetColor

CResolve->CClass.SetX

CResolve->CClass.SetY

(CResolve->CClass.SetWidth

CResolve->CClass.SetHeight

CResolve->CClass.SetAllOperation

CResolve->CClass.SetVctAllAttribute

CResolve->CClass.SetName

CResolve->CClass.SetX

CResolve->CClass.SetY

……

U2CChckerDlg->U2CChckerDlg.DrawRelationship

将上述调用跟踪发送到图7所示FSM。存在消耗事件U2CChckerDlg->CResolve.GetUMLFromXML的从当前状态q0出发的传出转移。该转移消耗该事件并将令牌移动到该转移的目标状态q2。类似地,依次消耗事件

CResolve->CResolve.GetClassFromXML

CResolve->CClass.SetColor

CResolve->CClass.SetX

CResolve->CClass.SetY

(CResolve->CClass.SetWidth

CResolve->CClass.SetHeight

CResolve->CClass.SetAllOperation

CResolve->CClass.SetVctAllAttribute

CResolve->CClass.SetName

此时令牌移动到状态q10(如图7所示)。对于事件CResolve->CClass.SetX,不存在消耗该事件的从q10出发的传出转移,但q10有一个接收空符号的转移,则令牌重新回到状态q3。此时存在消耗事件CResolve->CClass.SetX的从q3出发的传出转移,消耗该事件并将令牌移动到状态q4。重复这个过程,直到到达终结状态q46。说明方法调用跟踪与FMS一致。

导入非XML类型文件捕获到的方法调用跟踪如下:

U2CChckerDlg->CResolve.GetUMLFromXML

CResolve->CResolve.GetClassFromXML

CResolve->CClass.SetColor

CResolve->CClass.SetX

CResolve->CClass.SetY

(CResolve->CClass.SetWidth

CResolve->CClass.SetHeight

CResolve->CClass.SetAllOperation

CResolve->CClass.SetVctAllAttribute

CResolve->CClass.SetName

CResolve->CResolve.GetRelationshipFromXML

CResolve->CRelationship.SetColor

CResolve->CRelationship.SetRelationshipNo

CResolve->CRelationship.SetType

(CResolve->CRelationship.SetFromX

CResolve->CRelationship.SetFromY

CResolve->CRelationship.SetToX

CResolve->CRelationship.SetToY

CResolve->CRelationship.SetFromClass

CResolve->CRelationship.SetToClass

CResolve->CRelationship.SetXY

当令牌到达状态q22时,方法调用跟踪中的事件全部消耗,而此时FSM未到达终结状态,则说明不一致。事实上,对于UML顺序图,如果不是XML文件则直接退出。而源代码执行了一趟类和关系的解析过程后才退出(源代码未成功判断该文件不是XML格式)。如果不实际执行源代码只静态分析源代码(例如文献[17]),则无法发现该不一致。

4 实验及结果分析

在文献[19]的基础上,本文对UML模型与代码一致性检测工具U2C Checker1.0[20]进行了完善。为说明该工具的有效性,在开源项目LEDA 3.0[23]、zApp和ACD上进行了实验,并对实验结果进行了分析和讨论。

为方便进行实验,本文首先进行逆向工程,将3个开源项目的源代码转换成UML类图和序列图(这里认为转换得到的类图和序列图与源代码完全一致),并手动修改源代码构造出若干不一致。

本文对曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]进行了扩展,使得这些方法可以用于UML模型和C++代码的一致性检测。表1列出了使用上述3种方法以及本文方法检测出的不一致个数以及检出率。

表1 检测出的不一致个数

*检出率=总计检出个数/总计实际不一致个数

由表1可知,对于LEDA 3.0,在静态结构一致性检测中,这4种方法检测出的不一致个数相同,均为12处;在静态行为一致性检测中,曾一等方法[17]只考虑函数调用的时间顺序,并未考虑可选调用、循环和选择调用,因此只检测出5处不一致,而本文方法通过考虑可选调用、循环调用和供选择的调用,发现了曾一等方法[17]无法发现的更多不一致;在静态结构一致性检测和静态行为一致性检测的基础上,本文将运行期间实际发生的方法调用与UML模型相匹配,发现了6处曾一等方法[17]无法发现的不一致。曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]分别检测出17、12、12处不一致,检出率分别为51.52%、36.36%和36.36%,而本文方法检测出31处不一致,检出率达到93.94%,检出率有了明显提升。

类似地,对于开源项目zApp和ACD,本文方法也发现了比曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]更多的不一致,具有更高的检出率(如表1所示)。

5 结束语

为解决UML模型与源代码一致性检测问题,提出一种基于图论和FSM的UML模型与源代码一致性检测方法。在之前研究的基础上[20],本文讨论了基于FSM的UML模型与代码一致性动态检测方法。通过将运行期间实际发生的方法调用与UML模型进行匹配,对UML模型与代码的一致性进行动态检测。实验结果表明,该方法具有更高的检测准确率。

目前基于图论和FSM的UML模型与代码一致性检测方法仍存在一些缺陷和不足。今后的主要工作如下:

1)目前该方法在进行一致性检测时一旦发现不一致就会终止检测。后期将在此基础上进行改进,使得一次检测可以得到包含完整的不一致信息的报告清单。

2)该方法目前只考虑UML类图和顺序图,其他模型图(例如用例图、活动图和状态图等)与代码的一致性检测将在后续的研究中进行讨论。

3)目前该方法只能检测出UML模型与代码存在的不一致而不能自动对存在的不一致进行修改,如何对检测出的不一致进行自动修改也是下一步研究的重点。

猜你喜欢
源代码调用一致性
注重整体设计 凸显数与运算的一致性
商用车CCC认证一致性控制计划应用
基于TXL的源代码插桩技术研究
Why do we celebrate the New Year?
基于Paxos的分布式一致性算法的实现与优化
基于Android Broadcast的短信安全监听系统的设计和实现
保护好自己的“源代码”
解密别克安全“源代码”
利用RFC技术实现SAP系统接口通信
C++语言中函数参数传递方式剖析