巴元秀,趙逢禹,劉 亞
(上海理工大學 光電信息與計算機工程學院,上海 200093)
軟件項目復用對減少開發(fā)工作量和成本、提高軟件項目質量具有重要影響。在軟件開發(fā)中,通過復用技術可以充分利用已有的開發(fā)成果,從而提高軟件開發(fā)的效率、降低開發(fā)成本。同時,通過復用高質量的已有的開發(fā)產品,避免了重新開發(fā)過程中可能引入的錯誤,從而提高軟件的質量。
Gharehyazie等人利用代碼克隆檢測工具Deckard研究項目內部以及跨項目的克隆,研究發(fā)現代碼克隆非常普遍,從同一項目的幾行代碼到跨項目的代碼片段之間都檢測到不同程度的相似。Zhang Yun等人研究GitHub上的項目復用,發(fā)現含有相似的README文件的軟件項目存在相似性。由此可以看出不論是代碼級別還是項目級別,都存在著大量的復用。
目前最常用的軟件復用技術主要是代碼的復用。軟件開發(fā)人員在進行項目開發(fā)的過程中發(fā)現,開發(fā)同類型的軟件應用時會實現相似或相同的功能,相應的代碼實現也是相似的。代碼克隆技術便是代碼復用方法中最原始且最常用的技術,一般表示為開發(fā)人員通過代碼搜索技術從開源項目中找到自己所需要的源代碼并復制到自己的項目中。文獻[5]提出一種代碼級別的復用技術,該技術利用提取工具將源代碼的內容生成代碼摘要,將用戶輸入的文本與代碼摘要進行搜索查詢,最后獲取相似的代碼進行復用。
近年來,隨著開源生態(tài)的完善,人們更多地關注項目級別的復用研究。Xu等人研究跨項目復用,利用歷史開源軟件項目的描述文檔和源代碼,將其與待開發(fā)項目的功能進行相似性度量并推薦相似的軟件項目。Thung等人利用相似的項目會共享相似的第三方庫這一原理,提取開源項目使用的庫,利用對庫的相似性匹配相似的項目實現項目級別的復用。Nguyen等人提出生態(tài)系統(tǒng)概念,由歷史開源項目、庫以及項目之間的相互依賴關系組成,將開發(fā)人員對待開發(fā)項目的創(chuàng)建、修改等行為與生態(tài)系統(tǒng)分別構建成圖,利用圖的相似性算法選取相似的項目進行復用。
文獻[6~8]在項目級復用研究中仍有不足之處。文獻[6]主要研究了項目開發(fā)過程中跨項目的代碼復用技術,是編碼階段的復用方法。文獻[7]是從項目使用的庫方面考慮復用,文獻[8]是根據歷史開源項目、庫以及待開發(fā)項目三者之間的依賴關系考慮復用。以上的研究都還沒有實現從待開發(fā)項目的需求分析考慮項目級別的復用。
文獻[9]提出一種基于需求規(guī)范文檔進行代碼的功能特征復用的方法,該方法首先從需求規(guī)范文檔中提取出功能特征關鍵詞,然后將提取出的關鍵詞與代碼庫中代碼的功能特征關鍵詞進行相似性匹配,最后根據相似的功能特征進行代碼復用。文獻[9]從需求規(guī)范文檔的功能特征出發(fā),搜索可復用的代碼,仍然屬于項目局部功能的代碼復用。
在軟件工程實踐中,當開發(fā)人員獲取項目的軟件需求后,通常需要根據需求文檔中的問題領域、用例描述、數據模型E-R圖搜索開源項目庫中的相似軟件項目。如果能從需求文檔的問題領域、用例描述以及數據模型方面找到相似的歷史項目進行復用,可以大大節(jié)省項目設計與實施時間。而用自動化的方法找到相似的歷史項目,是一件復雜的工作。因此本文提出了一種基于軟件需求規(guī)范的的項目級復用方法PR-REQ(Project Reuse based on Requirements Specification)。該方法首先分析歷史開源項目,構建算法提取歷史項目核心信息,包括項目的領域信息、代碼的功能操作序列以及數據模型信息。然后針對待開發(fā)軟件項目的需求文檔,研究提取問題領域、用例的功能操作序列以及數據模型等信息的方法。最后分別構建領域相似性度量、功能操作序列相似性度量以及數據模型相似性度量算法,加權計算得到最終的相似性度量值并按由大到小排列。文中從GitHub上下載了8類Java web項目構造實驗,對本文提出的方法進行實證。
項目級別的復用是對歷史項目在軟件架構、功能實現、數據模型、設計與編碼等多方面的復用,也是軟件復用中最高級別的復用。為了實現項目級別的復用,圖1給出了該方法的操作流程圖,分為3步,它們分別是歷史開源項目信息的提取、待開發(fā)項目的需求文檔分析以及項目相似性度量計算。
(1)歷史開源項目信息的提取。
為了復用歷史項目,需要對開源歷史項目進行數據分析與特征提取。在每個項目中,大部分都有源代碼和描述文檔。源代碼包含了項目的功能信息和數據模型信息。描述文檔通常給出了項目的功能介紹、用法以及如何安裝或部署。
a.描述文檔領域信息的提取。
分析描述文檔中的項目功能介紹,利用自然語言的方法處理文本主題分析提取項目的領域信息。
b.代碼中功能信息的提取。
采用靜態(tài)代碼分析技術解析歷史項目的代碼,提取項目的各功能操作,構建項目的功能操作序列。
c.數據模型信息的提取。
從數據庫配置文件或源代碼中提取所使用的數據庫的表名、列名等信息,構建數據模型。
(2)待開發(fā)項目的需求文檔分析。
a.領域信息的提取。
在軟件復用時,屬于同一個領域的項目被復用的可能性更高。這里通過自然語言處理方法,對需求文檔進行分析,提取待開發(fā)項目的領域信息。
b.功能操作信息的提取。
為了從項目的功能方面進行相似性度量分析,需提取需求文檔中的用例,根據用例中的活動和參與活動的對象,構建待開發(fā)項目各功能的功能操作序列。
c.數據模型信息的提取。
在數據模型E-R圖中提取與待開發(fā)項目有關的實體信息。
(3)項目相似性度量。
a.領域相似性度量。
為了能夠根據需求文檔中的領域信息在歷史開源項目中尋找領域方面相似的項目,本文從開源歷史項目的描述文檔和待開發(fā)項目的需求文檔中各提取若干個主題,利用主題的相似性計算領域的相似度。a
=(a
,a
,…,a
)定義為從待開發(fā)項目的需求文檔描述中提取的n
維主題向量,b
=(b
,b
,…,b
)定義為從開源歷史項目的描述文檔中提取的n
維主題向量,領域相似度計算如公式(1)所示。
(1)
b.功能操作相似性度量。
為了從功能操作方面比較待開發(fā)項目的需求文檔和歷史開源項目之間的相似性,本文構建了功能操作序列的相似性度量方法。待開發(fā)項目的需求文檔中的功能操作序列定義為W
={W
,W
,…,W
},其中W
(i
=1,2,…,m
)代表一組功能操作序列的集合。歷史開源項目中提取的功能操作序列定義為T
={T
,T
,…,T
},其中T
(j
=1,2,…,n
)代表一組功能操作序列的集合。序列W
中序列的個數記為m
,序列T
中序列的個數記為n
,采用余弦相似度計算W
中任一個序列W
與T
中任一個序列T
的相似度值記為S
(W
,T
),最后根據公式(2)計算最終的相似度值。S
(W
,T
)=
(2)
c.數據模型相似性度量。
為了更準確地進行項目復用,本文對數據模型也進行分析,構建數據模型相似性分析。歷史開源項目中的數據模型定義為A
={A
,A
,…,A
},其中A
(j
=1,2,…,n
)代表由表名、列名信息組成的一組數據模型集合,集合A
中的個數記為n
。待開發(fā)項目的需求文檔中提取出的數據模型定義為C
={C
,C
,…,C
},其中C
(i
=1,2,…,m
)代表由需求文檔中表名、列名信息組成的一組數據模型集合,集合C
中的個數記為m
。采用余弦相似度計算集合A
中任一組數據模型A
與集合C
中任一組數據模型C
的相似度值記為S
(C
,A
),最后根據公式(3)計算集合C
與A
的相似度值。S
(C
,A
)=
(3)
d.計算候選項目的最終相似得分。
在分別計算上述三種相似度值后,最后采用公式(4)進行加權計算得到最終的相似性度量分值。

(4)
其中,α
代表領域信息的權重,β
代表功能操作序列的權重,γ
代表數據模型的權重。
圖1 PR-REQ方法流程圖
PR-REQ項目復用方法中的關鍵技術主要是從歷史開源項目與待開發(fā)項目的需求文檔中提取相關特征,然后計算這些特征的相似度并基于特征相似性推薦可復用的歷史項目。其中的關鍵技術主要有歷史開源項目信息的提取和待開發(fā)項目需求文檔信息的提取。
大多數開源項目中都有描述文檔和源代碼。為了分析歷史開源項目,本文對項目中包含的描述文檔和源代碼進行數據分析和特征提取。
(1)領域信息的提取
描述文檔是描述軟件項目信息的文檔,它一般包含軟件的基本功能、簡要的使用說明、代碼目錄結構說明等信息。文中使用斯坦福主題模型工具提供的基于概率模型的LDA主題模型算法對描述文檔中的項目功能介紹部分進行領域信息的主題提取。
在對領域描述文本進行數據提取等相關工作之前,一般要進行文本的預處理。文本的預處理也就是將需要進行分析的文本通過一定的方式轉換成方便處理的結構化的數據形式, 可以提高文本處理的準確性。需求規(guī)范文檔大多由中文文本構成,因此文中主要使用的預處理方式是中文文本的預處理。結合對于中文文本的特征進行分析,在研究的過程中,文本預處理方式主要包括語料庫清理、分詞、詞性標注和停止詞過濾。
①語料庫清理。
語料庫的清理主要是清理和刪除一些非法語言文字等不良數據。
②分詞、詞性標注。
詞是構成語句的基本單元,分析語句前需要先分詞,將文本中詞切分出來作為特征值,是自然語言處理比較重要的一步。中文分詞就是指將句子中漢字序列切分成詞集合。相對于英文而言,中文分詞要復雜得多。
③停止詞過濾。
在普通文本中含有標點符號、介詞、語氣詞等,這些詞對理解文本沒有實際意義,應從分詞結果中去除,這些詞稱之為停用詞。去停用詞可以省存儲空間,減少停用詞對理解語句造成的噪音,降低文本維度,可以提高處理文本的效率和準確率。
文獻[13]認為對一篇科技文獻,提取主題數量在5到6個時分析效果最好。借鑒該研究的結論,對軟件需求與歷史項目文檔的主題數量為5。
(2)代碼中功能操作序列的提取。
如何在軟件項目代碼中提取主要功能的操作序列是本文的關鍵算法。對于不同的軟件項目,由于其軟件架構不同,其功能的操作序列提取方法也有差異,但都可以通過對配置文件與源代碼的靜態(tài)分析獲得。文中以Java web項目為研究對象,給出特征提取算法。Java web項目的功能操作信息主要體現在項目的頁面文件上,因此文中針對Java web項目的頁面文件提取功能操作序列。為了從頁面文件中提取項目的功能操作,需要利用JSOUP解析器從應用程序的入口頁面開始對其進行數據解析,提取對應頁面的功能操作,構建功能操作序列。在提取功能操作時,在web頁面中,操作功能主要分為靜態(tài)和動態(tài)兩類。 就是一個靜態(tài)頁面的跳轉,可以從中提取出“注冊”功能; 是一個動態(tài)頁面的跳轉,在點擊“提交訂單”的同時會調用saveOrder方法,從后臺數據庫中調取數據,可以從中提取出“提交訂單”功能。算法1給出了代碼功能操作提取算法。
算法1:代碼功能操作提取算法。
輸入:Java web項目的頁面文件集合P
={p
,p
,…,p
},項目的配置文件config。輸出:項目的功能操作序列T
={T
,T
,…,T
},其中T
(i
=1,2,…,m
)為一組功能操作序列的集合處理:
1.初始化隊列Queue,G
={V
,E
},V
=Φ,E
=Φ;2.從config中找到項目的入口頁面文件,不失一般性假設為p
;3.將p
作為訪問的第一個頁面文件入隊列Queue;4.while(Queue非空)
{
CurrentPage=deQueue(Queue);//隊頭元素出隊;
V
=V
∪{CurrentPage};利用JSOUP解析器提取CurrentPage頁面中的功能操作信息f
和與之對應的跳轉頁面p
,p
∈P
;構造G
的有向邊,加入到集合E
中,記為E
=E
∪{<(CurrentPage,p
),f
>};if (p
not inV
)p
入隊列Queue;}
5.在圖G
中,從節(jié)點p
開始按照深度優(yōu)先算法遍歷路徑上的功能操作f
構造功能操作序列T
;6.輸出功能操作序列T
,結束算法。(3)數據模型的提取
算法以Java web項目的代碼文檔集合作為輸入,采用一種輕量級的查詢提取工具SQL提取器,該工具使用AST過程內的字符串解析,能夠對代碼中的數據模型進行靜態(tài)分析,提取出帶有元信息的SQL語句,通過對SQL語句進行分析,輸出含有數據庫的表名、列名信息的集合。文中給出了利用SQL提取器進行數據模型提取的過程,見算法2。
算法2:數據模型的提取。
輸入:項目的代碼文檔集合B
={b
,b
,…,b
}。輸出:表名、列名信息組成的數據模型集合A
={處理:
1.初始化集合A
;2.將b
作為訪問的第一個代碼文檔;3.for each (CurrentFile inB
){
利用SQL提取器提取出CurrentFile中SQL語句的表名和Insert語句中的列名,記為
A
=A
∪{對于待開發(fā)項目,需要在需求文檔中提取領域信息、功能操作信息、數據模型。其中領域信息的提取方法與歷史開源項目中提取領域信息的方法一致。數據模型的提取是對需求文檔的數據模型E-R圖中的實體關系進行分析。功能信息的提取是對需求文檔中的用例進行特征提取,提取用例的活動,構建待開發(fā)項目的功能操作序列。限于篇幅,文中主要介紹對需求文檔中的功能信息進行提取的方法。
用例由用例名稱、描述、角色、編號、前置條件以及主事件流等組成,文中給出了用例功能操作序列的提取算法,該算法使用需求文檔中的用例集合R
={r
,r
,…,r
}作為輸入,提取出與系統(tǒng)進行交互的用例活動,構建功能操作序列W
={W
,W
,…,W
}作為輸出,見算法3。算法3:用例功能特征的操作序列的提取。
輸入:需求文檔中的用例集合R
={r
,r
,…,r
}。輸出:功能操作序列W
={W
,W
,…,W
},其中W
(i
=1,2,…,m
)為一組功能操作序列的集合。處理:
1.初始化集合W
;2.將r
作為訪問的第一個用例;3.for each (CurrentUse inR
){
根據CurrentUse中的事件流的交互過程,提取出參與用例活動的操作和對應的活動對象,構建功能操作序列集合記為W
;W
=W
∪W
;}
4.輸出操作序列W
,結束算法。在軟件項目級別的復用研究領域中,目前尚沒有找到包含待開發(fā)項目的需求文檔、歷史項目的源代碼數據集,以及它們之間相似度的度量參考標準。因此為了驗證文中提出的PR-REQ方法的準確性,文中構造了一個實驗,采用人工方法和PR-REQ方法分別對需求文檔進行分析,將PR-REQ方法找出的Top N的相似軟件項目與人工找出的Top N的相似軟件項目進行一致性和包含性比較。
文中從GitHub上下載了958個Java Web項目,這些項目包含學校管理類、企業(yè)類、競賽類、網購類、游戲類等八類項目,在這些項目中同時具有需求描述和項目代碼的項目數共68個。開源軟件項目數及其類別見表1。

表1 開源軟件項目數及其類別
基于PR-REQ方法開發(fā)了一個項目復用推薦程序,該推薦程序首先從數據庫中讀取歷史開源項目和待開發(fā)項目的需求文檔。然后分別提取開源項目和需求文檔中的領域信息、功能操作序列以及數據模型信息并存儲于數據庫中。最后通過調用相似度量程序對需求文檔和歷史開源項目進行相似度量,利用相似度得分機制將候選項目按得分由大到小排列,并將候選項目的結果存儲到數據庫中。
為了驗證該方法的準確性,文中從百度文庫中下載了5個學校管理類需求文檔和5個企業(yè)類需求文檔,對其從①到⑩進行編號。為了便于實驗中對相似項目進行排序,將表1中同時具有需求描述和項目代碼的68個項目進行從1到68編號。其次,分別采用人工方法和PR-REQ方法對這10個需求文檔進行分析,從68個項目中找出相似的軟件項目。人工方法是由作者共同對每個需求文檔進行分析,從領域、功能操作以及數據模型三個方面進行數據分析,找出與之相似程度最高的3個項目,對其進行相似度排序并記錄3個項目對應的編號。PR-REQ方法則是利用開發(fā)好的項目復用推薦程序,對這10個需求文檔進行特征提取與分析,同樣找出與之相似程度最高的3個項目,對其進行相似度排序并記錄3個項目對應的編號。最后,分別對人工選取的項目和PR-REQ方法選取的項目進行一致率和包含率分析,驗證文中提出的PR-REQ方法的準確性。
定義1:一致率:PR-REQ系統(tǒng)找出的項目與人工找出的項目一致的比率。
定義2:包含率:PR-REQ系統(tǒng)找出的項目包含在人工找出的項目中的比率。
表2是針對每個需求文檔,利用人工方法和PR-REQ方法找出的相似軟件項目對應的編號。然后對表2中的編號進行一致率和包含率分析,分析結果見表3。

表2 人工方法和PR-REQ方法選取的相似項目的編號

表3 一致率和包含率分析 %
由表3可以看出,針對這10個需求文檔,人工分析與PR-REQ分析推薦的第一個歷史項目有80%相同,在推薦一個最相似的項目時,一致率與包含率意義相同。Top 2一致率為40%,Top 3一致率為30%,可以看出,隨著推薦的項目越多,一致率會有所下降,這一結果也符合預期;而對于包含率,Top 1、Top 2與Top 3都不低于80%,也就是說利用PR-REQ方法找出的1到3個相似項目與人工找出的1到3個相似項目雖然無法在相似程度上保持一致,但包含率在80%以上,這說明文中提出的PR-REQ方法具有較高的準確性,對于項目復用具有實用價值。
軟件項目需求分析是開發(fā)人員開發(fā)一個新項目時的第一階段,目前尚沒有一種項目復用方法可以根據待開發(fā)項目的需求文檔進行項目級復用。針對這一問題,文中提出了一種基于軟件需求分析的項目級復用方法PR-REQ,該方法從項目的主題領域、功能操作信息以及數據模型三個方面對待開發(fā)項目的需求文檔和開源歷史項目進行特征提取和數據分析,最后構建相似性度量方法進行相似項目推薦。基于文中提出的方法,隨機選取了企業(yè)類和學校管理類的需求文檔各5個來構造實驗驗證其準確性。
實驗結果表明,文中提出的基于需求分析的項目級復用方法在尋找相似的軟件項目方面具有較高的準確性,該方法對于開發(fā)人員在項目開發(fā)的初期階段具有重要作用。但是本實驗只取了68個歷史項目文件,針對兩類共10個項目需求文檔進行了分析,實驗樣本數量仍然偏少,為了證實該方法的實用性,還需下載更多的項目進行分析。另外對于非Java web項目,還需基于歷史項目的代碼進一步構建算法提取功能操作序列與項目的數據模型。