肖卓宇,何 锫,李 港,楊道武,彭逸凡,董澤民
1(中南林業科技大學 涉外學院,長沙 410200)
2(廣州大學 計算機科學與教育軟件學院,廣州 510006)
3(北京大學 高可信軟件技術教育部重點實驗室,北京 100871)
設計模式提供有效對象間關系的作用來實現某種設計意圖,并有助于程序的理解與復用[1].設計模式恢復與軟件系統的逆向工程與再工程聯系緊密,有利于遺產系統的維護與重構[2,3].為此,眾多學者圍繞設計模式檢測開展了大量的工作[4-7].
Fontana提出使用Design Pattern Clues、Micro Pattern、EDPS等微結構特征挖掘設計模式,從而實現對設計模式實例的識別[8,9].文獻[10]通過定義23種設計模式的子圖結構特征模型來實現對設計模式的挖掘.Rasool定義了47類特征信息,通過匹配特征信息來實現設計模式的恢復[11].文獻[12,13]構建了設計模式實例規則庫,并規范了模式庫與用例之間的映射關系.文獻[14]通過機器學習提升設計模式檢測的精確率.許涵斌等[15]提出通過查詢與匹配UML模型中的特征信息來恢復設計模式.Petterson提出影響設計模式恢復精度的幾種主要因素,而變體是因素之一[16].文獻[17] 提出一種形式化上下無關文法關系驅動的設計模式檢測方法,該方法能夠一定程度上減少設計模式參與者角色間附加關系導致的假陰性問題,并能較好的解決結構型模式的重疊問題.綜上所述,傳統的設計模式恢復方法存在5點問題:1) 較少考慮設計模式變體的影響,從而導致不精確的結果產生;2)對模式變體的挖掘沒有從創建型、行為型、結構型三個方面分類進行深入研究,缺乏針對性;3)傳統工作針對設計模式變體的理解側重于抽象概念,較少涉及具體的實現;4)對于模式變體的識別較少有檢測工具進行支撐;5)缺乏完整的設計模式變體知識庫.
為此,本研究引入了Petterson[16]提出的設計模式變體概念,并在Scanniello[1]提出設計模式變體影響程序理解的思想基礎上,提出一種注入間接線索的設計模式變體自動檢測方法.依據GOF(Gang of four,GOF)[2]的設計模式分類原則,從創建型、行為型、結構型模式三種分類著手,以Proxy、Command及Factory Method模式為例,在不改變設計意圖的前提下,分別給出了三者的模式變體實現,最后通過主流設計模式檢測工具進行了變體檢測實驗.本文主要貢獻為:1) 引入了設計模式變體的思想,提出一種可注入間接線索的設計模式變體自動識別方法.2) 從創建型、行為型、結構型模式三個角度出發對設計模式變體進行了研究與分析.3) 通過6種主流設計模式恢復工具與4種開源系統對設計模式變體的恢復結果進行了分析比較.
GOF[2]依據不同的設計意圖提出了23種經典的設計模式,而隨著設計模式思想與技術的成熟化與規模化,23種設計模式已不能完全滿足軟件設計的需要.事實上,為解決大中型軟件系統精準設計的需求,目前眾多研發人員在不改變設計意圖的前提下對23種經典設計模式進行了擴展,即設計模式變體[16].設計模式變體有利于軟件研發效率的提升,并降低成本,另一方面,從逆向工程與再工程的角度研究發現設計模式變體同時也會使得生成可復用解決方案變得困難,因為現有的工具與方法較難檢測出23種設計模式的變體.
本研究先前工作提出一種多階段交互式線索驅動的設計模式檢測方法,該方法取得較好的識別效果,但缺點在于人工干預太多,成本過高,并且對當前設計模式檢測領域的一個難點,即設計模式變體的檢測缺乏關注[13].本文先前工作對圖1中的標準Proxy模式的檢測效果較好,但對于Proxy模式變體的檢測效果不理想.
為此,本研究在先前工作[3]基礎上提出一種可注入間接線索的設計模式變體檢測方法,旨在不改變設計模式變體的設計意圖前提下,通過在標準設計模式中注入易被傳統設計模式檢測方法忽略的有價值間接關系來自動檢測設計模式變體,從而提高檢測結果的精確率.
定義1. 參與者角色及關系定義:
Rel:R×R,R∈{Interface,Class}.
Rel(R:R)={Ass,Dep,Agg,Inh...}.
R為模式實例參與者,可為接口Interface或類Class,Rel(R:R)表示設計模式參與者之間的聯系,可為關聯、依賴、繼承、聚合等.
定義2. 存在多層繼承的設計模式參與者角色關系定義:
?Inh(RA:RB)∧?Inh(RB:RC)→?Inh(RA:RC).
設計模式參與角色RA如與RB存在繼承關系,同時設計模式參與角色RB與RC也存在繼承關系,則設計模式參與角色RA與RC之間存在可傳遞的繼承關系.
定義3. 基于設計模式角色子繼承的關聯關系定義:
?Dep=(RA:RB)∧?Inh(RB:RC)→?Dep(RA:RC).
設計模式參與角色RA如與RB存在依賴關系,同時設計模式參與角色RB與RC也存在繼承關系,則設計模式參與角色RA與RC之間存在可傳遞的依賴關系.
先前工作[3]能檢測到圖1左側的標準Proxy模式,但如果將該標準設計模式演化為圖1右側的Proxy模式變體,本研究先前工作及傳統方法都難以檢測實現.與標準Proxy模式相比圖1右側的Proxy模式變體層次更多,關系也更加復雜,如RealSuject類參與者并沒有起到實質性作用,具體實現主要通過其子類RealSuject1與RealSuject2進行,而子類Re-alSuject1與RealSuject2雖未直接與Proxy類取得聯系,但由于類RealSubject1、RealSubject2與RealSubject存在繼承關系,依據3.1節定義3,故實質上RealSubject1可以通過圖1中關系1與Proxy類建立依賴聯系,并最終形成圖2中Proxy變體1;同理RealSubject2可以通過圖1中關系2與Proxy類建立依賴聯系,最終形成圖2中Proxy變體2.

圖2 Proxy模式變體子圖Fig.2 Subgraph variants of Proxy pattern
Guéhéneuc將設計模式表示為CSP[5]形式的約束集特征值,筆者先前工作[3]對其進行了初步標準設計模式檢測.表1描述了標準Proxy模式的CSP[5]表示形式,其中02行表示存在一個名為subject的超類,03行表示subject存在一個抽象方法,而04與05行表示Proxy類與Realsubject類都存在非抽象方法request,06行表示Proxy與subject類存在繼承關系,07表示Realsubject與subject類存在繼承關系,08行表示Proxy與Realsubject存在依賴關系.

表1 標準Proxy模式約束集Table 1 Constraints representation of standard Proxy pattern

表2 Proxy模式變體約束集Table 2 Constraints representation of variant Proxy pattern
圖2中Proxy變體1的CSP[5]表示見表2.與表1標準設計模式相比,注入間接線索后,Proxy變體1增加了新的特征信息.第06行表示類Realsubject1類也存在request方法,第09行表示Realsubject1與Realsubject之間也存在繼承關系,第11行表示Realsubject1子類與Proxy之間通過繼承傳遞也存在依賴關系,第12行表示參與者角色扮演的一致性檢驗結果.
步驟1. 通過工具DEMIMA[4]對目標源碼進行抽取.
步驟2. 遍歷步驟1抽取的參與者集,發現間接線索.
步驟3. 以CSP[5]的形式特征形式表示步驟2的間接線索.
步驟4. 通過特征匹配取得模式檢測結果.
GOF[2]將23種經典的設計模式分為結構型、行為型、創建型三類,事實上,在軟件設計過程中這三類設計模式將產生大量的變體.為此,在此分類基礎上,以Proxy模式、Command模式及Factory Method模式為例對三類變體依次進行詳細的研究與分析.
Proxy模式需要避免使用某些重量級的設計模式對象,而輕量級對象實質是原對象的副本,二者共享同一個接口,其具體實現僅通過最低功能配置生成.此外,Proxy模式與Decorator模式結構上相近,但二者意圖完全不同,故Proxy模式容易產生變體.圖3描述了4種Proxy模式變體.

圖3 四種Proxy模式變體Fig.3 Four variants of Proxy pattern
1)Proxy類與Subject類存在關聯關系的變體.Proxy類變體(1)結構與Decorator模式非常相似,區別在于Decorator模式的角色是抽象的,而Proxy模式變體(1)的角色是具體的.Proxy模式初始化了Subject與RealSubject類間的關聯關系,并實例化了Proxy類的構造函數.
2)Proxy類與RealSubject類間存在聚合關系的變體.該變體中Proxy類與RealSubject類之間存在聚合關系,這樣的處理方式有利于RealSubject類的參數實例化.該過程可能出現使用某種特定遠程對象類型的情況,而RealSubject類也將在構造函數級或方法級的層次上被初始化.
3)異構環境中的代理變體.這種變體中出現的Proxy類將方法調用委托給具體類,該過程引入代理線程,并可驗證.
4)反向代理變體.一個被Proxy類代理的客戶對象作為占位符進行反向的代理服務,該變體重定向了一個請求,并轉發請求,此外,一些可復用的服務可作為監聽器以確保需求透明.反向代理變體具備查詢有價值請求的功能.
上述4種形式未改變Proxy模式的意圖,可理解為典型的Proxy模式變體.
Command模式提供一種框架,該框架內數據的修改通過控制機制進行管理,Command模式用于對象間關系、職責的管理,適合于復雜場景,圖4描述了4種Command模式變體.
1)命令組合變體.該變體可使用多種命令進行遠程調用.
2)命令復用變體.這種變體集合了多種功能,此外,該變體對象中的參數可在不同的場景中復用.此變體的意圖是為了解決獨立執行、參數化及消除耦合等問題.
3)分布式命令模式變體.該變體引入相同命令自動調用的機制,提供一種從互聯系統調用命令的執行方式.該變體無需發送自定義消息來獲得服務器端數據,故在未通知命令執行的前提下,客戶端無需解析與發送消息.這種變體依據消息來獲取需要的數據與行為,每條命令都是序列化的發送給其它系統.
4) 裝飾模式命令變體.Facade 模式作為該變體的一個類被實現,并可通過用例的應用來發現相應的遠程方法,Command模式通過使用Facade 模式的用例或方法類來實現.

圖4 四種Command模式變體Fig.4 Four variants of Command pattern
Factory Method模式采用虛擬方法實現設計目標,該模式通過重寫子類來隱藏方法的實例邏輯,旨在通過工廠方法創建相似的對象.Factory Method模式有著廣泛的應用,如微軟的MFC,COM等.為此,創建型模式以Factory Method模式為例研究其7種典型變體.圖5描述了這7種Command模式變體.
1)參數工廠方法變體.這種變體側重Factory Method模式接口的參數化,提供了用于返回多個類型產品的單一工廠方法,故多個該變體可使用單一的方法,單一的抽象Product實例由每一個具體產品來創建.
2)從工廠方法中委派產品構建的變體.該變體使用語言特征機制在運行時動態的創建不同類型實例,旨在通過對工廠類的方法進行重寫來實現,并返回要創建的產品類型.如圖3中變體2)的ClientConfigurator類用來在一個特定時間選擇一個已注冊的具體類型.
3)無具體工廠類的變體.該變體通過消除子類具體的創建功能來實設計目標,Factory Method模式實例的創建由product類生成,product僅在創建類時被加載,Factory Method模式用于返回選定的product類.
4)從存儲庫類型中使用委托機制創建產品的變體.這種變體中product類由具體的創建者類庫生成,此外,需消除重寫的工廠方法,該變體主要在具體類構造時發生.
5)一個具體的創造者變體.該變體是參數工廠方法Factory Method模式變體1)的擴展,區別在于減少單一創建者的數量.
6)工廠內部不同產品類型變體.這種變體旨在提供Factory Method模式的基本實現,其中一個單一的工廠方法用來創建同類Product.該方法實現了多種Product類使用不同的工廠方法創建或訪問特定對象的功能,即模式的結構是相同的,但修改后的實現支持多個類型的Product.
7)默認產品實現變體.該變體擴展了Factory Method模式變體1)的不同產品類型,討論了默認模式執行所提供的Product類型,這種變體中Factory類與默認的Product類間存在直接的關聯關系.
設計模式的變體雖能更具針對性的解決某些特定問題,但同時也會影響設計模式檢測工具的精確性.為此,本實驗為檢測圖3、 圖4、 圖5中的設計模式變體,選擇主流設計模式恢復工具DeMIMA (Guéhéneuc,2008)[4]、PINOT(Shi and Olsson,2006)[19]、F.T.(Rasool,2011)[11]、DPRE(De Lucia et al.,2010)[20]、DPJF(Binun and Kniesel,2012)[18]進行了實驗.

表3 設計模式檢測工具參數表Table 3 Parameter table of design pattern detection tool
表3給出了設計模式檢測工具的部分重要參數,其中T列表示technique,涉及靜態分析(Static,S)與動態分析(Dynamic,D),R列表示識別方式Recognition,包括近似識別A(Approx,A)與完整識別E(Exact,E).實驗環境使用機操作系統為Windows 7,CPU為 Intel酷睿i5,主頻3.2 GHz,內存8G.
表4給出了圖3至圖5中4種結構性模式Proxy變體、4種行為型模式Comand變體、7種Factory Method模式變體通過表1描述的經典的設計模式檢測工具依次檢測后的結果.“√”表示檢測到了模式變體,“×”表示未檢測到的模式變體.分析表4后發現如下幾個主要問題:

圖5 7種Factory method模式變體Fig.5 Seven variants of factory method pattern
1)PINOT[19]及DeMIMA[4]工具不能識別任何一種行為型與創建型模式變體,深入研究后發現,這2種工具僅采用靜態分析機制,缺乏對檢測系統的動態分析.此外,由于PINOT工具對變體特征信息缺乏關注,從而導致任意的結構型Proxy模式變體都無法識別,而DeMIMA[4]工具雖然一定程度上關注了變體特征信息,但其關注范圍存在局限性,也導致結構型Proxy模式變體1)與3)不能被檢測到.

表4 設計模式變體實驗識別結果Table 4 Result on variants of design pattern
2)DPJF[18]工具由于同時兼顧了靜態分析與動態分析機制,一定程度上對結構性模式Proxy變體的檢測效果較PINOT[19]與DeMIMA[4]工具有所改進,甚至能夠識別部分行為型變體,如Command模式變體2)與4),但對創建型模式Factory Method變體的識別效果不理想.深入研究后發現創建型模式存在委托等難以復制的機制,對于對象執行的及時性與處理優先級等都有較高的要求,故識別的難度較高.
3)F.T[11]與DPRE[20]工具采用靜態與動態分析機制,并同時關注到了設計模式角色的附加關系[21]特征信息,故對于DPJF工具不能檢測到的創建型模式Factory Method變體的識別效果有所改進,如F.T[11]工具能夠識別Factory Method模式變體1),而DPRE工具能夠識別Factory Method模式變體2)與5).
4)本文工作兼顧了靜態分析與動態分析機制,并考慮到了設計模式角色間附加關系[21]與間接線索聯系的影響,故在設計模式變體檢測,尤其是創建型Factory Method模式變體的識別上取得了較好的效果.由表2可知,本文工作檢測出4種結構型Proxy變體、4種行為型Command模式變體及7種創建型Factory Method模式變體的精確率依次為100%、75%、57%,平均識別成功率達到73.3%,明顯高于F.T[11]等5種檢測工具的平均識別成功率26.67%.
5)由于GOF設計模式分類的意圖不一,故三類模式變體檢測成功的難易程度也不同,由表2結果可知創建型模式較難,行為型模式次之,結構型模式相對較易,三者平均識別率為16.67%、41.65%、58.33%.
該實驗中檢測工具選用表3中識別設計模式變體效果相對較好的F.T[11]與DPRE[20]工具,考慮到同行學者多以表5中開源系統進行檢測試驗,為了方便檢測結果交叉比較,故選擇表5中四種開源系統進行進一步的設計模式變體檢測實驗.表5描述了四種開源系統的網址、大小、LOC等主要參數.

表5 開源系統參數Table 5 Open source systems parameters
表6描述了開源系統中的變體檢測結果,實驗除分類識別標準的GOF設計模式之外,還對三類模式的變體進行檢測,如在QuickUML2001系統中,本文工作檢測到3個標準的Proxy模式及1個Proxy模式變體.工具F.T[11]僅檢測到3個標準的Proxy模式,但不能識別Proxy模式變體.DPRE[20]工具能正確識別出Proxy模式變體,但只能識別2個標準的Proxy模式.為此,筆者以人工形式查找發現DPRE[20]工具未能識別的標準Proxy模式實例存在實例共享的問題,即Proxy模式中的參與者同時扮演多個設計模式中的角色,由于DPRE[20]工具缺乏這類約束機制,以至于識別結果不精確,而本文工作兼顧了靜態與動態分析,關注到了設計模式角色間的附加關系[21]與間接線索聯系的影響,故在該實驗中取得了較好的效果.
1www.sourceforge. net/projects/quj/
2www.jrefactory.sourceforge.net
3www.antapache.org
4www.jhotdraw.org
依據GOF[2]的設計模式分類原則,第6節中將設計模式變體分為結構型、行為型、創建型三類.所有三類模式變體的意圖需與基于GOF的標準設計模式意圖一致.而實際應用中結構型與行為型變體應用相對較多,因為結構型與行為型變體能夠通過細微的修改來實現針對性的目標,且不改變標準GOF模式的意圖,故較容易形成成熟的解決方案.
從一個逆向的角度來看,設計模式檢測工具也應敏銳的意識到這些變體,因為軟件系統中可能廣泛存在這樣的變體,而開發人員也傾向于復用這樣的變體以提高軟件研發的效率.這是一種機遇,也是一種挑戰,為此,總結了將設計模式變體轉換為可復用解決方案應注意的8項事項.
1)因為模式變體的不同實現,使得目前缺乏一種變體識別標準.
2)當前一些研究人員對設計模式檢測的用例基準進行了分析與評估,但對模式變體的定義與識別基準缺乏關注.
3)一些變體僅根據作者突然的靈感或隨機場景偶然的應用產生,故缺乏歸納.
4)新的變體需要在已有的模式定義中通過增加特征實現,而這些特征的獲取方式仍無基準.
5)即便當前主流的工具也不能檢測所有的模式變體.
6)大多數檢測工具僅限于特定的設計模式,或某種特定的編程語言.
7)參與者共享設計模式角色也是變體產生的一個主要因素.
8)設計模式變體的假陽性及假陰性結果影響解決方案復用的效率.
本研究引入Petterson[16]提出的設計模式變體思想,并結合Scanniello[1]提出設計模式變體影響程序理解的觀點,提出一種注入間接線索的設計模式變體檢測方法.依據設計模式變體與標準模式意圖的一致性原則,對設計模式變體進行了分類研究與識別.
1)與傳統設計模式變體側重理論相比,本研究給出了具體的設計模式變體檢測實踐.
2)分類描述了創建型、行為型及結構型模式變體的多種實現,并依次分類歸納了多種經典的Proxy模式、Command模式及Factory Method模式變體.
3)通過多種經典檢測工具對三類模式變體進行了檢測比較,并分類歸納總結了影響三類設計模式變體檢測結果精確率的原因.研究工作取得了一定的成效,具備較好的應用前景,基本達到了預期目標.但也要意識到設計模式變體研究是一項長期的過程,并值得進一步深入研究,未來工作將致力于設計模式變體的歸納、定義、恢復及模式變體庫的完善.
:
[1] Scanniello G,Gravino C,Risi M,et al.Documenting design-pattern instances:a family of experiments on source-code comprehensibility[J].ACM Transactions on Software Engineering and Methodology,2015,24(3):1-41.
[2] Zhang C,Budgen D.What do we know about the effectiveness of software design patterns[J].IEEE Transactions on Software Engineering,2012,38(5):1213-1231.
[3] Xiao Zhuo-yu,He Pei,Yu Bo.A multi-stage approach based on interactive clues for design pattern detection[J].Journal of Beijing University of Aeronautics and Astronautics,2017,43(9):1746-1756.
[4] Gueheneuc Y G,Antoniol G.DeMIMA:a multilayered approach for design pattern identification[J].IEEE Transactions on Software Engineering,2008,34(5):667-684.
[5] Gueheneuc Y G,Guyomarch J Y,Sahraoui H.Improving design-pattern identification:a new approach and an exploratory study[J].Software Quality Journal,2010,18(1):145-174.
[6] Xiao Zhuo-yu,Li Yan,He Pei,et al.Research on matrix grade evaluation based on design pattern detection[J].Journal of Chinese Computer Systems,2016,37(7):1428-1433.
[7] Xiao Zhuo-yu,He Pei,Yang Xin-wei,et al.An optimization method for design pattern identification based on the grammar production[J].Journal of University of Electronic Science and Technology of China,2017,46(3):569-576.
[8] Fontana F A,Maggioni S,Raibulet C.Design patterns:a survey on their micro-structures[J].Journal of Software:Evolution and Process,2013,25(1):27-52.
[9] Fontana F A,Maggioni S,Raibulet C.Understanding the relevance of micro-structures for design patterns detection[J].Journal of Systems and Software,2011,84(12):2334-2347.
[10] Yu D,Zhang Y,Chen Z.A comprehensive approach to the recovery of design pattern instances based on sub-patterns and method signatures[J].Journal of Systems and Software,2015,88(5):1-16.
[11] Rasool G,Mader P.A customizable approach to design patterns recognition based on feature types[J].Arabian Journal for Science and Engineering,2014,39(12):8851-8873.
[12] Ampatzoglou A,Charalampidou S,Stamelos I.Research state of the art on GoF design patterns:a mapping study[J].Journal of Systems and Software,2013,86(7):1945-1964.
[13] Ampatzoglou A,Michou O,Stamelos I.Building and mining a repository of design pattern instances:practical and research benefits[J].Entertainment Computing,2013,4(2):131-142.
[14] Zanoni M,Fontana F A,Stella F.On applying machine learning techniques for design pattern detection[J].Journal of Systems and Software,2015,88(5):102-117.
[15] Xu Han-bin,Zhang Xue-lin,Zhen Xiao-mei,et al.Method of software design patterns identification based on correlation and feature constraints[J].Computer Science,2014,41(11):50-55.
[16] Petterson N,Lowe W,Nivre J.Evaluation of accuracy in design pattern occurrence detection[J].IEEE Transactions on Software Engineering,2010,36(4):575-590.
[17] Xiao Zhuo-yu,He Pei,Yu Bo,et al.An approach for design pattern detection based on the formal context-free grammar relation driver[J].Chinese Journal of Engineering,2016,38(10):1499-1508.
[18] Binun A,Kniesel G.DPJF-design pattern detection with high accuracy[C].Software Maintenance and Reengineering (CSMR),2012 16th European Conference on.Szeged:IEEE,2012:245-254.
[19] Shi N,Olsson R A.Reverse engineering of design patterns from java source code[C].Automated Software Engineering,ASE′06,21st IEEE/ACM International Conference on Automated Software Engineering (ASE′06),Tokyo:IEEE,2006:123-134.
[20] De lucia A,Deufemia V,Gravino C,et al.An eclipse plug-in for the detection of design pattern instances through static and dynamic analysis[C].Software Maintenance (ICSM),2010 IEEE International Conference on,Timisoara:IEEE,2010:1-6.
[21] Xiao Zhuo-yu,He Pei,Li Yan.Study on the additional relationships based on design pattens′s roles[J].Application Research of Computers,2015,32(7):2042-2045.
附中文參考文獻:
[3] 肖卓宇,何 锫,余 波.一種多階段交互式線索驅動的設計模式識別方法[J].北京航空航天大學學報,2017,43(9):1746-1756.
[6] 肖卓宇,黎 妍,何 锫,等.基于矩陣積分評估的設計模式檢測研究[J].小型微型計算機系統,2016,37(7):1428-1433.
[7] 肖卓宇,何 锫,楊鑫維,等.基于文法產生式優化的設計模式識別方法[J].電子科技大學學報,2017,46(3):569-576.
[15] 許涵斌,張學林,鄭曉梅,等.一種基于結構查詢的UML設計模式識別方法[J].計算機科學,2014,41(11):50-55.
[17] 肖卓宇,何 锫,余 波,等.一種形式化上下無關文法關系驅動的設計模式檢測方法[J].工程科學學報,2016,38(10):1499-1508.
[21] 肖卓宇,何 锫,黎 妍.基于設計模式角色的附加關系檢測研究[J].計算機應用研究,2015,32(7):2042-2045.