王 雷,張 帥,宋慧娜
(1.延安大學(xué) 數(shù)學(xué)與計(jì)算機(jī)科學(xué)學(xué)院;2.陜西省能源大數(shù)據(jù)智能處理省市共建重點(diǎn)實(shí)驗(yàn)室; 3.延安大學(xué) 上海文思海輝聯(lián)合實(shí)驗(yàn)室(大數(shù)據(jù)應(yīng)用開發(fā)方向),陜西 延安 716000)
UML[1]是目前面向?qū)ο蟪绦蛟O(shè)計(jì)中使用最廣泛的建模技術(shù)。在基于UML的軟件開發(fā)過程中,應(yīng)用程序員需要根據(jù)UML面向?qū)ο蠓治雠c設(shè)計(jì)結(jié)果來編寫程序。然而,在實(shí)際的編程過程中,往往會因?yàn)閼?yīng)用程序員的個(gè)人水平、軟件設(shè)計(jì)師和應(yīng)用程序員存在理解偏差以及趕進(jìn)度和節(jié)約成本等各種各樣的原因?qū)е耈ML模型與編寫的源代碼之間存在不一致。此外,敏捷開發(fā)模式已經(jīng)成為目前軟件領(lǐng)域的主流開發(fā)方法之一[2]。該開發(fā)方法強(qiáng)調(diào)可運(yùn)行的軟件勝過寬泛的文檔,強(qiáng)調(diào)對變更的響應(yīng)勝過按部就班的遵循計(jì)劃[3-4]。因此,對于使用敏捷開發(fā)方法構(gòu)建的軟件系統(tǒng),UML模型與源代碼的不一致問題更為嚴(yán)重。使用軟件工程工具自動檢測出UML模型與源代碼之間存在的不一致并對存在的不一致進(jìn)行修改,可以為軟件項(xiàng)目,尤其是大型軟件項(xiàng)目后期的理解、維護(hù)和重構(gòu)提供便利。近10年來,隨著物聯(lián)網(wǎng)、大數(shù)據(jù)、云計(jì)算、人工智能等前沿技術(shù)的興起,軟件系統(tǒng)的規(guī)模越來越大,復(fù)雜程序越來越高,UML模型與源代碼一致性檢測的研究就變得越來越有必要。
目前國內(nèi)外有很多學(xué)者致力于UML的各種模型之間一致性檢測問題的研究。例如,Ekanayake等[5]提出一種UML類圖和順序圖一致性檢測方法;Yao等[6]、錢成等[7]、杜杰等[8]研究了基于模型檢測的UML順序圖和狀態(tài)圖一致性檢測;Chanda等[9]提出一種UML類圖、用例圖和活動圖之間的一致性檢測方法;Khai等[10]給出一種基于Prolog的UML類圖和順序圖一致性檢測方法;Kowal等在文獻(xiàn)[11-12]中提出一種基于UML的多層建模方法,并在文獻(xiàn)[13]中討論了不同級別的UML模型的一致性檢測;Straeten等[14]提出一種基于描述邏輯(description logic)的UML模型不同版本之間的一致性檢測和解決方法;Long等[15]、Chama等[16]探索了由UML模型自動生成一致性代碼的方法。這些文獻(xiàn)均無法對源代碼和UML模型之間的不一致進(jìn)行檢測。
針對UML模型與代碼之間的一致性檢測的研究還比較少。曾一等[17]通過對Java源代碼的詞法分析和語法分析獲取類的信息及方法調(diào)用圖(CG,call graph),然后將類的信息以及CG與UML模型進(jìn)行匹配;Pires等[18]自動生成從UML類圖到Java代碼的設(shè)計(jì)測試,這些代碼扮演設(shè)計(jì)測試和實(shí)現(xiàn)語言的雙重角色;Chavez等[19]試圖檢查在測試用例上調(diào)用Java程序之后生成的狀態(tài)是否與UML設(shè)計(jì)類圖關(guān)聯(lián)的所有約束一致。這些方法都未通過動態(tài)執(zhí)行源代碼來檢測UML模型與代碼的一致性,因此這些方法無法檢測出只有通過動態(tài)執(zhí)行源代碼才能發(fā)現(xiàn)的不一致。
針對以上問題,提出一種基于圖論和FSM的UML模型與源代碼一致性檢測方法。在之前的研究中[20],已經(jīng)討論了基于圖論的UML模型(目前只考慮UML類圖和順序圖)與源代碼一致性靜態(tài)檢測方法,并初步討論了UML模型與代碼一致性動態(tài)檢測。在此基礎(chǔ)上,本文討論了基于FSM的UML模型與代碼一致性動態(tài)檢測方法。該方法執(zhí)行源代碼并捕獲方法調(diào)用跟蹤,將捕獲的方法調(diào)用與UML順序圖轉(zhuǎn)換得到的FSM進(jìn)行匹配,以此來檢測動態(tài)行為的一致性。實(shí)驗(yàn)結(jié)果表明,在基于圖論的UML模型與代碼一致性靜態(tài)檢測的基礎(chǔ)上,該方法可以對UML模型與代碼的一致性進(jìn)行動態(tài)檢測。相對于僅進(jìn)行靜態(tài)檢測的方法,本文可以檢測出更多的不一致,具有更高的檢測準(zhǔn)確率。
在前期研究中[20],作者提出一種基于圖論和FSM的UML模型與源代碼一致性檢測方法,基本思路如圖1所示。
UML模型與代碼的一致性靜態(tài)檢測已經(jīng)在文獻(xiàn)[20]中進(jìn)行了詳細(xì)討論,本文接著進(jìn)行一致性動態(tài)檢測以提高檢測的精確率。
UML模型與代碼一致性動態(tài)檢測的基本流程是:首先將UML順序圖轉(zhuǎn)換為FSM。然后監(jiān)視正在分析的程序的函數(shù)調(diào)用,并將它們與UML順序圖轉(zhuǎn)換得到的FSM進(jìn)行匹配。若匹配不成功則說明存在不一致,修改源代碼直到源代碼的動態(tài)行為與UML順序圖完全一致。
圖1 基于圖論和FSM的UML模型與源代碼 一致性檢測基本思路
要使用FSM的驗(yàn)證技術(shù)對UML順序圖和源代碼進(jìn)行一致性檢測,首先需要將UML順序圖轉(zhuǎn)換為FSM模型。UML 2.0序列圖有兩類基本元素:函數(shù)調(diào)用和交互片段。下面定義從序列圖的兩種基本元素到FSM的轉(zhuǎn)換規(guī)則(本文借鑒了文獻(xiàn)[21]轉(zhuǎn)換方法并對其進(jìn)行了細(xì)化)。
1)函數(shù)調(diào)用
規(guī)則1 對于函數(shù)調(diào)用,轉(zhuǎn)換為兩個(gè)狀態(tài)和他們之間的轉(zhuǎn)移。如圖2所示。
圖2 函數(shù)調(diào)用到FSM的轉(zhuǎn)換
其中轉(zhuǎn)移接收的符號由來源于順序圖的變量的連結(jié)組成:調(diào)用者的類對象(A),調(diào)用符號“->”,被調(diào)用者的類(B),以及被調(diào)用函數(shù)m1(后兩者用點(diǎn)分隔)。
對于兩個(gè)順序的函數(shù)調(diào)用,將二者分別按照規(guī)則1轉(zhuǎn)換,然后將第一個(gè)調(diào)用的FSM的結(jié)束狀態(tài)與第二個(gè)調(diào)用的FSM的開始狀態(tài)合并。如圖3所示。
圖3 順序調(diào)用到FSM的轉(zhuǎn)換
2)交互片段
規(guī)則2 對于可選(optional)調(diào)用,轉(zhuǎn)換為兩個(gè)狀態(tài)和他們之間的兩個(gè)轉(zhuǎn)移。其中一個(gè)轉(zhuǎn)移接收的符號同普通函數(shù)調(diào)用,另一個(gè)接收空符號ε。如圖4所示。
圖4 可選調(diào)用到FSM的轉(zhuǎn)換
規(guī)則3 對于循環(huán)(loop),轉(zhuǎn)換為一個(gè)開始狀態(tài)和一個(gè)結(jié)束狀態(tài),再加一個(gè)接收空符號的轉(zhuǎn)移。該轉(zhuǎn)移直接從結(jié)束狀態(tài)到開始狀態(tài)來重復(fù)循環(huán)。如圖5所示。
圖5 循環(huán)到FSM的轉(zhuǎn)換
規(guī)則4 對于若干個(gè)供選擇的(alternative)調(diào)用,轉(zhuǎn)換為兩個(gè)狀態(tài)和他們之間的若干個(gè)轉(zhuǎn)移。每個(gè)轉(zhuǎn)移接收的符號對應(yīng)一個(gè)分支。如圖6所示。
圖6 供選擇的調(diào)用到FSM的轉(zhuǎn)換
這里繼續(xù)以筆者所在實(shí)驗(yàn)室研發(fā)的UML模型正確性檢測工具UML Checker1.0[22]為例來說明UML順序圖到FSM的轉(zhuǎn)換。根據(jù)上述轉(zhuǎn)換規(guī)則,將文獻(xiàn)[20]中圖3所示UML順序圖轉(zhuǎn)換為FSM模型,如圖7所示(標(biāo)有箭頭的節(jié)點(diǎn)表示初始狀態(tài),雙圈節(jié)點(diǎn)表示終結(jié)狀態(tài))。
將UML順序圖轉(zhuǎn)換為FSM后,就可以監(jiān)視正在分析的程序的函數(shù)調(diào)用并將其與轉(zhuǎn)換得到的FSM進(jìn)行匹配。詳細(xì)步驟如下:
步驟1 對于每個(gè)待檢測功能模塊,設(shè)計(jì)合適的測試用例。
步驟2 對于每個(gè)測試用例,執(zhí)行源代碼并捕獲方法調(diào)用跟蹤。
步驟3 將捕獲到的方法調(diào)用跟蹤發(fā)送到FSM。這里為FSM的狀態(tài)引入一個(gè)令牌(Token)(圖7中的黑點(diǎn))。令牌在FSM中的位置表示FSM當(dāng)前的狀態(tài)。從初始狀態(tài)出發(fā),依次檢測是否存在消耗方法調(diào)用跟蹤中的事件的從當(dāng)前狀態(tài)出發(fā)的傳出轉(zhuǎn)移。事件的調(diào)用者和被調(diào)用者的類和方法必須匹配轉(zhuǎn)換符號中指定的類和方法。如果匹配成功,那么轉(zhuǎn)移會消耗該事件并將令牌移動到轉(zhuǎn)移的目標(biāo)狀態(tài)。
圖7 模型導(dǎo)入功能的UML順序圖的FSM表示
步驟4 若方法調(diào)用跟蹤中的事件全部匹配成功,同時(shí)FSM到達(dá)終結(jié)狀態(tài),則說明方法調(diào)用跟蹤與FSM一致。否則給出不一致說明并手動修改源代碼直到方法調(diào)用跟蹤與FSM完全一致。
繼續(xù)以UML Checker1.0為例來說明UML順序圖和源代碼的動態(tài)行為一致性檢測。這里為UMLChecker1.0的模型導(dǎo)入功能提供兩個(gè)測試用例:一個(gè)XML格式文件作為正常輸入,一個(gè)非XML格式文件作為異常輸入。導(dǎo)入XML格式文件捕獲到的方法調(diào)用跟蹤如下(只列出前12個(gè)方法調(diào)用事件和最后一個(gè)調(diào)用事件):
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
將上述調(diào)用跟蹤發(fā)送到圖7所示FSM。存在消耗事件U2CChckerDlg->CResolve.GetUMLFromXML的從當(dāng)前狀態(tài)q0出發(fā)的傳出轉(zhuǎn)移。該轉(zhuǎn)移消耗該事件并將令牌移動到該轉(zhuǎn)移的目標(biāo)狀態(tài)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
此時(shí)令牌移動到狀態(tài)q10(如圖7所示)。對于事件CResolve->CClass.SetX,不存在消耗該事件的從q10出發(fā)的傳出轉(zhuǎn)移,但q10有一個(gè)接收空符號的轉(zhuǎn)移,則令牌重新回到狀態(tài)q3。此時(shí)存在消耗事件CResolve->CClass.SetX的從q3出發(fā)的傳出轉(zhuǎn)移,消耗該事件并將令牌移動到狀態(tài)q4。重復(fù)這個(gè)過程,直到到達(dá)終結(jié)狀態(tài)q46。說明方法調(diào)用跟蹤與FMS一致。
導(dǎo)入非XML類型文件捕獲到的方法調(diào)用跟蹤如下:
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
當(dāng)令牌到達(dá)狀態(tài)q22時(shí),方法調(diào)用跟蹤中的事件全部消耗,而此時(shí)FSM未到達(dá)終結(jié)狀態(tài),則說明不一致。事實(shí)上,對于UML順序圖,如果不是XML文件則直接退出。而源代碼執(zhí)行了一趟類和關(guān)系的解析過程后才退出(源代碼未成功判斷該文件不是XML格式)。如果不實(shí)際執(zhí)行源代碼只靜態(tài)分析源代碼(例如文獻(xiàn)[17]),則無法發(fā)現(xiàn)該不一致。
在文獻(xiàn)[19]的基礎(chǔ)上,本文對UML模型與代碼一致性檢測工具U2C Checker1.0[20]進(jìn)行了完善。為說明該工具的有效性,在開源項(xiàng)目LEDA 3.0[23]、zApp和ACD上進(jìn)行了實(shí)驗(yàn),并對實(shí)驗(yàn)結(jié)果進(jìn)行了分析和討論。
為方便進(jìn)行實(shí)驗(yàn),本文首先進(jìn)行逆向工程,將3個(gè)開源項(xiàng)目的源代碼轉(zhuǎn)換成UML類圖和序列圖(這里認(rèn)為轉(zhuǎn)換得到的類圖和序列圖與源代碼完全一致),并手動修改源代碼構(gòu)造出若干不一致。
本文對曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]進(jìn)行了擴(kuò)展,使得這些方法可以用于UML模型和C++代碼的一致性檢測。表1列出了使用上述3種方法以及本文方法檢測出的不一致個(gè)數(shù)以及檢出率。
表1 檢測出的不一致個(gè)數(shù)
*檢出率=總計(jì)檢出個(gè)數(shù)/總計(jì)實(shí)際不一致個(gè)數(shù)
由表1可知,對于LEDA 3.0,在靜態(tài)結(jié)構(gòu)一致性檢測中,這4種方法檢測出的不一致個(gè)數(shù)相同,均為12處;在靜態(tài)行為一致性檢測中,曾一等方法[17]只考慮函數(shù)調(diào)用的時(shí)間順序,并未考慮可選調(diào)用、循環(huán)和選擇調(diào)用,因此只檢測出5處不一致,而本文方法通過考慮可選調(diào)用、循環(huán)調(diào)用和供選擇的調(diào)用,發(fā)現(xiàn)了曾一等方法[17]無法發(fā)現(xiàn)的更多不一致;在靜態(tài)結(jié)構(gòu)一致性檢測和靜態(tài)行為一致性檢測的基礎(chǔ)上,本文將運(yùn)行期間實(shí)際發(fā)生的方法調(diào)用與UML模型相匹配,發(fā)現(xiàn)了6處曾一等方法[17]無法發(fā)現(xiàn)的不一致。曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]分別檢測出17、12、12處不一致,檢出率分別為51.52%、36.36%和36.36%,而本文方法檢測出31處不一致,檢出率達(dá)到93.94%,檢出率有了明顯提升。
類似地,對于開源項(xiàng)目zApp和ACD,本文方法也發(fā)現(xiàn)了比曾一等方法[17]、Pires等方法[18]和Chavez等方法[19]更多的不一致,具有更高的檢出率(如表1所示)。
為解決UML模型與源代碼一致性檢測問題,提出一種基于圖論和FSM的UML模型與源代碼一致性檢測方法。在之前研究的基礎(chǔ)上[20],本文討論了基于FSM的UML模型與代碼一致性動態(tài)檢測方法。通過將運(yùn)行期間實(shí)際發(fā)生的方法調(diào)用與UML模型進(jìn)行匹配,對UML模型與代碼的一致性進(jìn)行動態(tài)檢測。實(shí)驗(yàn)結(jié)果表明,該方法具有更高的檢測準(zhǔn)確率。
目前基于圖論和FSM的UML模型與代碼一致性檢測方法仍存在一些缺陷和不足。今后的主要工作如下:
1)目前該方法在進(jìn)行一致性檢測時(shí)一旦發(fā)現(xiàn)不一致就會終止檢測。后期將在此基礎(chǔ)上進(jìn)行改進(jìn),使得一次檢測可以得到包含完整的不一致信息的報(bào)告清單。
2)該方法目前只考慮UML類圖和順序圖,其他模型圖(例如用例圖、活動圖和狀態(tài)圖等)與代碼的一致性檢測將在后續(xù)的研究中進(jìn)行討論。
3)目前該方法只能檢測出UML模型與代碼存在的不一致而不能自動對存在的不一致進(jìn)行修改,如何對檢測出的不一致進(jìn)行自動修改也是下一步研究的重點(diǎn)。