本發(fā)明涉及的是一種在源碼工程中搜索相應功能的方法。
背景技術:
:隨著互聯(lián)網(wǎng)和開源軟件的欣欣向榮和蓬勃發(fā)展,開發(fā)者接觸到的代碼越來越多,同時這些軟件的架構也越來越復雜。開源代碼的發(fā)展越來越好,開源工程也越來越大,理解并在其基礎上開發(fā)也越來越困難。在這時根據(jù)關鍵詞返回功能而不是代碼片段能極大的提高開發(fā)者的效率。通過閱讀相關文獻和實驗數(shù)據(jù)分析,發(fā)現(xiàn)源碼功能定位的主要問題在于搜索和功能確定。軟件聚類是聚類的一種特殊應用。軟件聚類由于能分解出其中的結構和模塊,由此得到發(fā)展的機會。也正因為此,本發(fā)明采用軟件聚類來得到功能模塊,也用以過濾檢索結果。正因為其應用場景的特殊性,國內(nèi)外眾多學者在其上也各自發(fā)展出了琳瑯滿目的理論。軟件聚類共有三個過程,分別是聚類對象描述、策略以及算法。近幾年的發(fā)展,在這三個方面都有所進展。以聚類對象描述為例,近幾年共提出了三種聚類對象描述方法,分別是形式化描述、非形式化描述以及多視圖描述方法。Scanniello針對面向?qū)ο笳Z言提出一種多階段聚類的方法。該方法共分為兩個階段,第一個階段,使用LSI等字詞方法,將聚類對象分成多個組;第二個階段,使用形式化方法將聚類對象分解成多個簇。由此獲取最終的聚類。在信息檢索領域,檢索關鍵詞有很多方法。如果針對文本文件,使用正則表達式、VSM或者主題模型都可以完成檢索的功能。傳統(tǒng)的源碼搜索技術通常是根據(jù)關鍵字,查詢相似代碼片段,如GitHub、GoogleCode,其得到的都是工程中相似的文本片段或者包含查詢關鍵字的代碼片段。技術實現(xiàn)要素:本發(fā)明的目的在于提供一種能得到較為精確的類結構信息的基于軟件聚類的源碼功能搜索方法。本發(fā)明的目的是這樣實現(xiàn)的:首先輸入源碼,對源碼進行語法檢查和類信息的獲取,然后分為兩個模塊完成搜索過程,即軟件聚類模塊和功能搜索模塊。軟件聚類模塊從獲取的類信息中,篩選實體并且構造實體索引,然后進行提取特征和構造特征向量,然后通過層次聚類篩選信息,并將結果存儲。功能搜索模塊從獲取的類信息中,構造輸入集且完成主題分析,然后進行索引構造并存儲索引。輸入關鍵詞檢索,即可得到檢索結果,本發(fā)明操作流程如附圖1所示。功能搜索模塊根據(jù)輸入的查詢詞定位得到類結構信息;軟件聚類模塊篩選功能搜索模塊得到的類結構信息,得到更加精確的信息。本發(fā)明的還可以包括:1、所述的針對軟件工程的特征包含形式化分析特征和非形式化分析特征,所述形式化分析特征描述包括:(1)類泛化關系,(2)類實現(xiàn)關系,(3)類依賴關系,(4)包關系,(5)文件依賴關系;所述非形式化分析特征描述包括:(1)變量名稱特征,(2)文件名稱特征;通過靜態(tài)分析的方法,包括詞法分析和語法分析源碼文件,得到形式化特征描述;如果是簡單的類關系則通過詞法分析,如果涉及到編譯時才能卻確定的關系,則通過語法分析篩選得到更準確的關系,所述編譯時才能卻確定的關系包括模板或泛型。2、構造針對軟件工程的特征向量過程使用類繼承距離、包距離,所述類繼承距離定義如下:(1)A類繼承B類則繼承距離為1,A類繼承B類的特征值為1;(2)繼承距離為N,則相應的特征值為1×λinheritN-1;所述包距離的定義如下:(1)A類中使用了PackageP則包距離為1,其特征值為1;(2)包距離為N,則相應的特征值為1×∈pppackageN-1。在靜態(tài)分析提取的特征基礎上,計算特征向量,構造特征矩陣。3、變量名稱和文件名稱特征,提取后的后續(xù)處理包括以下兩步:(1)變量和文件名稱拆分,(2)停用詞過濾,變量和文件名稱拆分依照用戶自定義的變量命名規(guī)則來拆分,所述命名規(guī)則包括:駝峰命名法、匈牙利命名法;停用詞中共有兩部分,一部分是常見的無意義詞語,包括of、a或者中文的“是”;另外一部分是源碼中的關鍵字,當涉及到中文時,單獨進行分詞處理。4、篩選的過程包括:(1)搜索只是得到相似度達到閾值的結果;(2)這些結果經(jīng)過軟件聚類得到的簇篩選,篩選條件是這些結果在簇中占用的比例也達到了閾值;(3)經(jīng)過篩選后,調(diào)整顯示結果,輸出類信息。本發(fā)明提出針對Java的軟件特征提取方法和特征向量構造方式。構造的特征矩陣作為層次聚類算法的輸入,輸出相應的簇描述。然后,提出了針對類結構的主題分析方法。該方法不以文件為單位,只針對類結構信息分析。由此搜索得到的將不再是代碼片段,而是和功能相關的一系列類結構信息。最終,綜合利用軟件聚類和主題分析實現(xiàn)了功能搜索技術。在軟件聚類提取構造特征向量時,對于類繼承關系,每一個類都作為一個聚類實體,同時每一個類都是一維特征。如果類和類之間有繼承關系,則特征值取為1。類直接繼承的關系用1來表示外,間接繼承也使用1表示。因為如果A類繼承于C類,B類也繼承于C類,A類還繼承與B類,但A類、B類在和C類的關系的強度上是不同的。所以本發(fā)明在類繼承關系中添加繼承距離。直接繼承關系繼承距離為1,每增加一層繼承,繼承距離就增加1。而最終的特征值添加一個權值λinherit。其表現(xiàn)形式如下:(1)A類繼承B類則繼承距離為1,A類繼承B類的特征值為1;(2)繼承距離為N,則特征值為1×λinheritN-1。上述的特征矩陣將根據(jù)繼承距離做相應的修改。設其中一個類的特征向量為V=[v0v1…vn-1]繼承距離向量為D=V=[d0d1…dn-1]則最終的特征向量為:W=V×DT=v0v1...vn-1×λinheritd0-1λinheritd1-1...λinheritdn-1-1]]>在計算最終的特征時,以的方式來表示類繼承關系的逐漸減弱。對于包關系,和類繼承關系提取特征向量類似,包距離的定義如下:(1)A類中使用PackageP則包距離為1,特征值為1;(2)包距離為N,則特征值為1×∈pppackageN-1。特征向量提取構造完成之后,求解所有實體之間的距離,即構造聚類實體距離矩陣。構造一個N×N的矩陣,其中元素表示N個實體之間的距離。每一個實體都是一個N維向量,表示實體和其他實體的距離。在聚類過程中,需不斷計算各個簇之間的距離,并根據(jù)結果合并兩個簇來構造新簇。使用凝聚時層次聚類算法完成軟件聚類的功能。在確定聚類實體矩陣和簇間距離之后,使用本發(fā)明提出的軟件聚類算法,具體步驟為:首先提取源碼特征實體,即各個類信息;然后獲取源碼中各個實體的具體信息,其中包括類間關系、文件關系以及附加關系;然后根據(jù)提取的信息構造特征向量;之后使用凝聚時算法完成聚類,然后結合各個實體之間的具體信息,輸出可視化聚類結果。對于針對源碼的主題分析方法,使用LSI算法進行主題分析,和傳統(tǒng)方法稍有不同的是本發(fā)明提出的LSI方法針對的是每一個經(jīng)過處理后的類信息。本發(fā)明結合源碼檢索和軟件聚類,使用多階段將更方便。和Scanniello的方法不同,本發(fā)明主要目的不是軟件聚類,但是可以采用將多階段聚類方法應用到本發(fā)明的技術中去。在其他方法中,忽略了一個重要的因素,那就是聚類過程中應該提取哪些特征、怎么提取以及特征向量、特征矩陣該如何構造等問題。雖然本發(fā)明中的定位和源碼搜索中的搜索相關,但由于面向的對象不同,并不適合完全照搬搜索引擎。搜索引擎所關注的是如何找到給定輸入的代碼或者相關的代碼,提供給用戶的只是某一段可能符合要求的代碼或注釋,并不會提供給用戶和某一個關鍵詞相關的類結構等信息,也就不能反映該查詢詞對應的功能模塊。源碼搜索得到的是大量工程、大量的代碼片段,而本發(fā)明致力于得到詳細的類結構信息。本發(fā)明結合軟件聚類,提出的功能搜索技術除能得到相似的代碼片段外,還能得到和查詢詞相關的功能模塊。對于面向?qū)ο蟮恼Z言,其輸出為類結構信息。經(jīng)過軟件聚類的過濾,部分和功能結構無關的文本信息將被剔除,輸出更加精確的結果。軟件聚類針對不同的源碼,相同的參數(shù)將獲取不同的結果,為解決該問題,聚類的參數(shù)可以相應選擇和更改,以滿足用戶輸入不同的項目和不同階段的閱讀。發(fā)明的有益效果為:本發(fā)明提出一種結合軟件聚類的功能搜索技術,使用主題分析和軟件聚類,該技術能得到較為精確的類結構信息。本發(fā)明提出針對Java的軟件特征提取方法和特征向量構造方式。構造的特征矩陣作為層次聚類算法的輸入,輸出相應的簇描述。在構造特征向量時,本發(fā)明使用類繼承距離和包距離,可以反映出類之間及包之間的關系,在通過簇間距離計算后,通過凝聚式聚類算法找到相似度最大的兩個簇(即距離最小的兩個簇)并合并,更準確的完成聚類功能。本發(fā)明提出了針對類結構的主題分析方法。使用針對類結構的主題分析方法。該方法不以文件為單位,只針對類結構信息分析。由此搜索得到的將不再是代碼片段,而是和功能相關的一系列類結構信息。使用軟件聚類的結果指導主題分析,主題分析的輸出經(jīng)過軟件聚類過濾,最終展現(xiàn)給用戶更加精確的信息。本發(fā)明綜合利用軟件聚類和主題分析實現(xiàn)了功能搜索技術。結合軟件聚類,提出的功能搜索技術除能得到相似的代碼片段外,還能得到和查詢詞相關的功能模塊。對于面向?qū)ο蟮恼Z言,其輸出為類結構信息。經(jīng)過軟件聚類的過濾,部分和功能結構無關的文本信息將被剔除,輸出更加精確的結果。軟件聚類針對不同的源碼,相同的參數(shù)將獲取不同的結果,為解決該問題,聚類的參數(shù)可以相應選擇和更改,以滿足用戶輸入不同的項目和不同階段的閱讀。如果軟件的設計和結構比較差,聚類將會根據(jù)功能的不同,和參數(shù)不同,得到合適的功能模塊劃分,這也是軟件聚類的一個優(yōu)勢。經(jīng)實驗驗證,本發(fā)明所設計的原型系統(tǒng)能按照關鍵字查詢得到功能模塊所涉及的類結構。而相對于代碼片段的查找,因為經(jīng)過軟件聚類得到的簇篩選,所以能更好地過濾一些無效數(shù)據(jù)。附圖說明圖1為系統(tǒng)總體框圖;圖2為常用實體距離計算函數(shù);圖3為手動添加輸出類信息的部分類結構;圖4為本發(fā)明系統(tǒng)搜索得到的部分結果;圖5為GitHub搜索SSA得到的結果統(tǒng)計;圖6為和GitHub篩選結果比較;圖7為GitHub搜索SSA得到的測試結果;圖8為GitHub搜索SSA得到的文本文檔;圖9為GitHub搜索SSA得到Command模塊的結果。具體實施方式下面結合附圖舉例對本發(fā)明進行詳細說明。本發(fā)明分為軟件聚類模塊和功能搜索模塊。針對于軟件聚類模塊中,本發(fā)明提出的軟件聚類算法具體步驟如下:步驟1:提取源碼特征實體,也就是各個類信息;步驟2:獲取源碼中各個實體的具體信息,其中包括類間關系、文件關系以及附加關系;步驟3:根據(jù)提取的信息構造特征向量;步驟4:使用凝聚式算法聚類;步驟5:結合第2步提取的信息,輸出可視化聚類結果。提取類信息使用Doxygen。它直接使用Lex解析Java代碼,在提取信息之前,需手動編譯檢查語法無誤。語法有錯雖能正常解析,但解析得到的結果并不完整。Doxygen的運行其需要讀取一個配置文件Doxyfile。Doxyfile中比較有兩個比較重要的參數(shù),分別是EXTRACT_ALL=YES和RECURSIVE=YES,這兩個參數(shù)分別表示解析所有的內(nèi)容和文件夾遞歸解析。Doxygen本身并不帶有輸出類信息的功能,需要手動在其中添加類信息處理方法。添加新類Features以及相應的方法PrintClassesRelations和PrintClassesInNamespace。部分類結構描述如附圖3所示。特征向量構造使用Python語言完成,讀入的是Doxygen輸出的各類信息,然后設置相應的參數(shù),構造特征向量。使用列表(list)來存儲特征向量。之后使用Python的scipy庫,設定參數(shù),使用各類層次聚類算法即可完成所需要的聚類。在根據(jù)提取的信息構造特征向量時,使用類繼承距離、包距離。類繼承距離的定義如下:(1)A類繼承B類則繼承距離為1,A類繼承B類的特征值為1;(2)繼承距離為N,則相應的特征值為1×λinheritN-1。包距離的定義如下:(1)A類中使用了PackageP則包距離為1,其特征值為1;(2)包距離為N,則相應的特征值為1×∈pppackageN-1。由于凝聚式層次算法的輸入是所有實體之間的距離。所以構造特征向量之后,通過距離函數(shù)計算聚類實體距離,并構造實體距離矩陣。假設有兩個實體A和B,其中A=[a1a2…an],B=[b1b2…bn],常用的距離計算方法如附圖2所示。常見的距離計算方法有歐式距離、曼哈頓距離、切比雪夫距離、閔可夫斯基距離、標準化歐氏距離、馬氏距離、夾角余弦。然后計算簇間距離。在聚類過程中,需不斷計算各個簇之間的距離,并根據(jù)結果合并兩個簇來構造新簇。首先假設有兩個簇,U和V,其中u1,u2,…,un為簇U中的實體,v1,v2,…,v3為簇V中的實體。U是新簇,且由簇S和T組合而成。則每一個新簇U和其他簇V之間的距離為d(U,V)。簇距離的計算有以下幾種計算方式:單連接算法SLA:簇的相似度是兩個簇中所有的實體兩兩之間的最大相似度。也就是取任意實體ui∈U和任意實體vj∈V,計算ui和vj距離的最小值。對于任意的U中的ui和V中的vj,其距離公式如公式1所示。d(U,V)=min(dist(u[i],v[j]))公式1全連接算法CLA:簇的相似度是兩個簇中所有實體、兩兩之間最大相似度。對于任意的i和j,其中ui∈U和vj∈V,其距離計算公式如公式2所示。d(U,V)=max(dist(u[i],v[j]))公式2平均連接算法ULA:計算簇的相似度方式是兩個簇中所有實體的相似度的總和的平均值。對于任意的i和j,其中ui∈U和vj∈V,其距離計算公式如公式3所示。加權平均連接算法WLA:根據(jù)組合成新簇的兩個簇分別和其他簇之間的距離和的均值計算得到距離。對于簇S和簇T組成新的簇U,其簇U和任意其他簇V之間的相似度計算方式如公式4所示。質(zhì)心聚類方法:以兩個簇S和簇T的質(zhì)心之間的歐拉距離作為其相似度,計算公式如公式5所示。當簇S和簇T合并一起的時,將遍歷所有簇中的實體,并重新計算新簇的質(zhì)心。之后得到的相似度是該新簇的質(zhì)心和森林中其他簇的質(zhì)心之間的歐拉距離。d(S,T)=||as-at||公式5離方差平方和法:計算公式如公式6所示。離差平方和的大小反映了分類是否合理。若類間離差平方和較大,而數(shù)據(jù)點間卻較小,則分類效果就比較合理。在使用該方法時,初始輸入的特征向量的距離一定是歐拉距離。相似度計算方法直接影響聚類效率和聚類結果。單連接聚類算法和全連接算法是其中最為簡單、最為高效的算法,離方差平方和法雖計算較為復雜,但往往效果較好。針對不同的應用場景需要選擇不同的計算方法。然后根據(jù)凝聚式層次聚類算法完成實體的聚類功能。凝聚式聚類算法的一般步驟如下:步驟0:構造有N個待聚類的實體;步驟1:將每一個待聚類的實體歸為一簇,共有N簇;步驟2:如果只有一個簇,結束;否則,計算簇兩兩之間的距離;步驟3:找到相似度最大的兩個簇,也就是距離最小的兩個簇,假設為s和t,合并s和t為u;步驟4:重新計算新的簇u和其他簇(不包括s、t和u)之間的距離;步驟5:回到步驟2。而針對于功能搜索模塊中,本發(fā)明在Doxygen基礎上,實現(xiàn)靜態(tài)分析工具用于提取類信息,本發(fā)明使用LSI(淺層語義索引)算法完成主題分析的功能。功能搜索模塊中需要使用主題分析方法構造針對軟件工程源碼的索引。使用步驟如下:步驟1:文本預處理;步驟2:構建詞袋(Bag-of-Words);步驟3:轉(zhuǎn)化為文檔向量;步驟4:訓練TF-IDF模型;步驟5:訓練LSI模型;步驟6:創(chuàng)建索引;步驟7:查詢詞余弦相似度。作為輸入的文本文件是由一定的語言編寫而成,如雜志、書籍等自然語言編寫而成的,或者是某些結構化語言編寫而成,如HTML、C語言等。在本發(fā)明中,以提取出的類信息作為輸入。如果直接處理這些輸入,將得到不準確的結果。如HTML中語言的標簽會擾亂模型的構建、自然語言中的一些語氣詞、停用詞等都會影響最終模型的建立,Java語言中的關鍵字也同樣回有影響。因為這些標簽或者詞組對理解文檔并沒有什么作用,它們在其中只是起到了強調(diào)、轉(zhuǎn)接詞句或者提示作用。所以預處理階段就需要過濾這些詞組。針對源碼主要有兩種類型的詞語要過濾:(1)英文中的停用詞;(2)源碼中的標識符。本發(fā)明所涉及的系統(tǒng)針對的是Java語言,所以其過濾的關鍵字符有:網(wǎng)絡上自然語言中的停用詞有多個版本是,大致相同,挑選一個即可。預處理常見內(nèi)容有小寫化、tokenize、stemming以及低頻詞的過濾。在源碼中,還包括:(1)組合單詞過濾(2)根據(jù)命名規(guī)則,去掉無意義詞語。不同的軟件工程中有不同的變量命名規(guī)則,在Java中通常采用的命名規(guī)則是方法名用動詞,若是由多個動詞組成,則每一個動詞都首字母都大寫;變量用名詞,多用小寫字母開始,若有多個名詞,則除第一個單詞外,后續(xù)的單詞首字母都是大寫等等。根據(jù)這些命名規(guī)則,在一定程度上可以過濾掉這些內(nèi)容。我們需要做的是根據(jù)規(guī)則,分解這些命名,然后以此過程過濾掉停用詞,因為根據(jù)系統(tǒng)功能不同,停用詞列表也不同,用戶因此可以配置哪些能過濾,哪些不能過濾。詞袋(Bag-of-Words)是指所有文件出現(xiàn)的所有單詞。對于中文的文檔,需要先進行分詞,分詞之后的數(shù)據(jù)才能進一步放入詞袋。構建詞袋的同時,需要將所有的出現(xiàn)的詞(token)映射為相應的ID。不同的詞有不同的ID,通過ID即可表示為該詞組。同樣的,所有的文檔也可以像詞袋的token-id映射一樣,用ID映射到對應的文檔。使用映射后ID就可以采用向量化的表示方式表示文檔了。在向量化表示文檔后開始訓練TF-IDF模型。訓練結束后,每一個文檔都會被表示為TF-IDF向量。訓練的好壞一方面看預處理的結果,另外一方面看輸入的文檔。這也是為什么前面的預處理如此重要的原因。TF-IDF表示的文檔向量作為輸入即可訓練LSI模型。訓練過程中需指定訓練主題數(shù),其對應SVD分解時需要指定的維數(shù),通過軟件聚類才可確定。為了能正常查詢關鍵字或者比較幾個不同的類之間的相似度,需要構建所有文檔的索引。對于輸入的查詢詞,只要將其映射到主題空間,通過余弦相似度即可查找和其最相似的文檔。最終按照相似度排序,輸出達到閾值的結果。整體實驗驗證使用AndroidDx工具,輸入查詢詞“ssa”,得到的結果如附圖4所示(由于查詢結果太多,只展示部分結果),展示本發(fā)明系統(tǒng)搜索得到的部分結果。使用GitHub在相同的工程中搜索同樣的關鍵字,得到和Java源碼相關的55個結果。結果順序是按照關鍵字的匹配程度顯示的,其中一條結果如附圖5所示。本發(fā)明設計的原型系統(tǒng)結果與之比較如附圖6所示,其中的數(shù)字代表結果數(shù)量。查詢結果總數(shù)為查詢關鍵字后得到的所有結果的數(shù)量。從這點來看,GitHub和未經(jīng)軟件篩選的查詢結果數(shù)量接近。而之所以在數(shù)量上有細微差別,其中一個原因是GitHub只能針對全工程搜索,而本發(fā)明所設計的原型系統(tǒng)中不僅可以指定目錄搜索,還可以先排除掉部分目錄不搜索。所以GitHub中包含了一部分和源碼無關的內(nèi)容,使得結果數(shù)相對較多,如附圖7所示的測試代碼在本發(fā)明中就不再包含。另外一個原因是GitHub搜索了非源碼文件,如文本文檔,本發(fā)明設計的系統(tǒng)在LSI階段就排除附圖8所示的文本文檔。相應的,對應的無關源碼數(shù)就為0。不論是GitHub還是本發(fā)明系統(tǒng),搜索得到的50個結果都包含部分無效數(shù)據(jù),因為源碼注釋中不可避免地包含了一部分的噪聲。和GitHub不同的是,經(jīng)過聚類篩選后,排除了絕大多數(shù)的無效數(shù)據(jù),其中只包含4個無效數(shù)據(jù)。GitHub由于只是關鍵字匹配以及輸出匹配的代碼片段,統(tǒng)計所得包含了27個無效的數(shù)據(jù)。這些無效數(shù)據(jù)只能由人工篩選出符合要求的結果。如附圖9所示,Main函數(shù)雖然有ssa的字樣,但是該模塊完成的功能是參數(shù)選項過濾,所以不應該在搜索得到的功能模塊中。綜上所述,本發(fā)明所設計的原型系統(tǒng)能按照關鍵字查詢得到功能模塊所涉及的類結構。而相對于代碼片段的查找,因為經(jīng)過軟件聚類得到的簇篩選,所以能更好地過濾一些無效數(shù)據(jù)。當前第1頁1 2 3