楊瀟
摘要:設(shè)計模式是面向?qū)ο蟮能浖_發(fā)中一種可重用的、能夠解決軟件設(shè)計開發(fā)中普遍存在問題的方法。識別軟件系統(tǒng)中的設(shè)計模式能夠幫助相關(guān)開發(fā)人員和維護人員更好的理解軟件系統(tǒng)的設(shè)計。尤其是GoF[1]中的結(jié)構(gòu)型設(shè)計模式,解決了如何組合類和對象獲得更大結(jié)構(gòu)的設(shè)計問題。所以對于結(jié)構(gòu)型設(shè)計模式的識別能夠有效地提高軟件的理解和可維護性。在該論文中展示了是一種識別面向?qū)ο筌浖到y(tǒng)中設(shè)計模式的方法。該方法能夠自動的識別出軟件系統(tǒng)中的結(jié)構(gòu)型設(shè)計模式。
關(guān)鍵詞:設(shè)計模式檢測;源代碼分析;逆向工程
中圖分類號:TP311 文獻標(biāo)識碼:A 文章編號:1009-3044(2015)08-0236-04
Abstract: Design Patterns are reusable design elements in object-oriented software design and development. Design Patterns aim at providing solutions for recurring design problems in software development. Detecting design patterns in existing software systems can improve the comprehension of software systems. The structural design patterns mentioned in GoF Patterns[1] are concerned with how classes and objects are composed to form larger structures. Thus, detecting structural design patterns are extremely useful for software comprehension and maintenance. In this paper I present an approach to detect design patterns in object-oriented software systems. It is an approach for automatically detection of structural design patterns.
Key words: design pattern detection; source code analysis; reverse engineering
1 課題背景
對軟件系統(tǒng)的全面深入理解對于現(xiàn)代軟件工程的發(fā)展有著舉足輕重的作用。因為軟件理解是保證軟件有效維護和再工程的一個重要因素[2]。隨著軟件規(guī)模的日益增大,軟件理解的工作變得越發(fā)的重要。
如果軟件系統(tǒng)具有完整的文檔信息,那么想要全面理解一個已有系統(tǒng)也并非難事。但是,現(xiàn)實的狀況是在軟件開發(fā)的過程中相關(guān)文檔缺失、不全面,或者文檔與系統(tǒng)不一致。這樣則給軟件理解造成了很大的阻礙。由此也導(dǎo)致了軟件維護和再工程的代價昂貴、需要耗費大量的人力物力或者根本無法得以繼續(xù)。
由于設(shè)計模式中包含了解決一般常見設(shè)計問題的通用解決方法,尤其是其中的結(jié)構(gòu)型設(shè)計模式,通過繼承機制或者對象組合的方式使得類和對象能夠相互組合并構(gòu)成更大的系統(tǒng)。所以提取結(jié)構(gòu)型設(shè)計模式的相關(guān)信息能夠幫助我們更加充分的理解系統(tǒng)。
2 識別過程
本論文中所研究的設(shè)計模式識別算法是基于抽象語法樹靜態(tài)分析的自動化識別。其基本方法如圖1所示.
2.1 從源代碼生成抽象語法樹
本論文所提出的設(shè)計模式識別方法是基于源代碼靜態(tài)分析的。在本文的識別方法中,首先是根據(jù)源代碼構(gòu)建其抽象語法樹模型。通過抽象語法樹模型的建立,得到程序在更高抽象層面上的表示。再對抽象語法樹進行分析,能夠有效簡化源代碼分析的復(fù)雜度。抽象語法樹的生成,基于第三方開源工具RECODER[3]來實現(xiàn)。
2.2分析抽象語法書得到設(shè)計模式候選實例
設(shè)計模式候選實例識別的過程,概括的說即是分析設(shè)計模式類圖,分解類圖中各角色的相互關(guān)系;根據(jù)分解關(guān)系設(shè)計算法流程搜索程序的抽象語法樹模型,得到滿足關(guān)系的設(shè)計模式候選實例的過程。
在本論文中,采用元組的方式來描述一個設(shè)計模式實例,即對于任何一個設(shè)計模式實例,采用Design Pattern:(Role A, Role B, Role C)
的形式來表達(dá)。
而在分析和分解設(shè)計模式類圖各角色的相互關(guān)系時,本文只關(guān)注一下三種類型的關(guān)系,即繼承、代理、組合關(guān)系。本文約定用這三種關(guān)系來表示一個設(shè)計模式所需要滿足必要條件,同時采用如下表達(dá)式來表示繼承、代理、組合關(guān)系:
1) 繼承關(guān)系:Inheritance(Super Class, Sub Class)
2) 代理關(guān)系:Delegation(Delegator, Delegatee)
3)組合關(guān)系:Composition(Container, Containee)
具體地,對抽象語法樹進行分析識別設(shè)計模式候選實例的過程,可以分解為如圖2所示的三個步驟:
1)確定設(shè)計模式實例的元組表示
[1]中包含了所有結(jié)構(gòu)型模式的結(jié)構(gòu)圖。而確定設(shè)計模式元組表示的過程,即是將結(jié)構(gòu)圖中除Client之外的所有角色表示為一個N元組。
2)分析設(shè)計模式類圖并分解出各角色間的繼承、代理、組合關(guān)系
繼承關(guān)系和組合關(guān)系在UML類圖中是非常明顯的,可以直接找出。而代理關(guān)系則是通過兩點判斷:一、判斷在類圖中存在的依賴關(guān)系是否為代理關(guān)系,若是則直接找出;二、根據(jù)類圖所給注釋推斷出隱含的代理關(guān)系。
3)設(shè)計候選實例識別算法流程
模式候選實例算法的起點均為遍歷系統(tǒng)中所有的類。在遍歷的過程中,根據(jù)類、對象間的關(guān)系逐步找到滿足步驟2關(guān)系的元組。
在設(shè)計模式候選實例識別算法的設(shè)計過程中,需要遵循以下幾個原則:
①根據(jù)類的繼承層次自底向上分析
② 優(yōu)先獲取繼承相關(guān)類
2.3約束條件檢查
對已經(jīng)識別出的實例進行進一步檢查,以剔除其中不符合約束的實例。需要明確的一點是,候選實例識別的過程是從整個系統(tǒng)進行搜索;而約束檢查則僅針對已經(jīng)識別出的候選實例。
約束條件的檢查過程如圖3所示。
1)候選實例角色完備性約束檢查
在文本所述設(shè)計模式候選實例的識別過程中,候選實例是根據(jù)類圖的分解關(guān)系搜索抽象語法樹模型得到的,可能會出現(xiàn)角色對應(yīng)類為空的情況。所以,我們需要檢查候選集中每個實例的角色完備性。
2)自身約束條件檢查
對抽象語法樹進行分析得到候選實例的過程,是根據(jù)類與對象間的相互關(guān)系進行信息提取、判斷而得到設(shè)計模式實例的過程。這個過程,主要關(guān)注的是類與類的相互關(guān)系 ,而忽略了類本身的一些屬性。所以為了增加識別的準(zhǔn)確性,我們還需要從類自身的一些屬性出發(fā)檢查。
自身約束條件主要考慮以下兩個方面:
① 訪問權(quán)限修飾符
訪問權(quán)限修飾符在編程語言中具體所指為public private protected 關(guān)鍵字。
在本文的方法中只檢查角色對應(yīng)類是否被public關(guān)鍵字所修飾,約定該約束使用表達(dá)式IsPublic( Class ) 表示一個類被public關(guān)鍵字修飾。
② 類類型
在本文中,類類型指的一個類(Class)是接口、抽象類還是具體類。
設(shè)計模式的類類型約束,可以直接通過設(shè)計模式類圖得出。
3)不存在關(guān)系檢查
候選實例的識別過程中,算法設(shè)計只考慮了設(shè)計模式中角色與角色之間的必要關(guān)系。除了存在的必要關(guān)系,在設(shè)計模式各角色間可能還有不存在關(guān)系。
同樣的,在不存在關(guān)系的檢查中,本文同樣也只針對繼承關(guān)系、代理關(guān)系和組合關(guān)系進行檢查。
2.4 Adapter模式實例
本小節(jié)將以Adapter模式的識別過程為例具體闡述本文所論述的設(shè)計模式識別一般方法是如何變?yōu)榫唧w的識別流程的。
3 實驗
對本文提出的方法,我們在一些開源項目中進行了實驗。在此,三種不同版本的JHotDraw項目(5.1, 6.0b1和7.0.6),和J2SE 5.0中的java.*包。
J2SE是Java 2標(biāo)準(zhǔn)版的縮寫[4],其中包含構(gòu)成Java語言核心的類。JHotDraw是一個二維GUI繪制的Java框架[5]。
本實驗環(huán)節(jié)中對Adapter, Composite和Decorator三種模式做了實驗,得到的結(jié)果如下:
4 結(jié)論與展望
本論文提出了一種結(jié)構(gòu)型設(shè)計模式的自動化識別過程。旨在通過這樣的方式來更好的支持對軟件系統(tǒng)的理解。該方法首先將源代碼轉(zhuǎn)換成抽象語法樹,并使用靜態(tài)分析的方法對其進行分析以得到軟件系統(tǒng)中的設(shè)計模式實例。
同時,本文使用提出的方法進行了實驗,通過對實驗環(huán)節(jié)得到的多組數(shù)據(jù)進行分析,驗證了本文所述算法的能夠較為有效的識別實際項目中存在的設(shè)計模式實例。
本論文雖然提出了一個通用的結(jié)構(gòu)型設(shè)計模式識別的通用算法設(shè)計原則和流程。但是對于每一種設(shè)計模式的具體設(shè)別過程,依舊需要具體模式具體分析。所以,在之后的研究中希望能夠進一步增強算法的通用性,由此來提高該自動化識別方法的可擴展性。
參考文獻:
[1] Gamma E,Helm R,Johnson R,et al.Design Patterns: Elements of Reusable Object-Oriented Software[M].Addison-Wesley,1995.
[2] Pacione M J,Roper M,Wood M.A novel software visualisation model to support software comprehension[C].Reverse Engineering Proceedings.11th Working Conference on,2004:70-79.
[3] RECODER Main Page[EB/OL].http://recoder.sf.net.
[4] J2SE 5 Source Code[EB/OL].http://www.oracle.com/technetwork/java/javase/downloads/index.html.
[5] JHotDraw Start Page[EB/OL].http://www.jhotdraw.org.