摘 要: 隨著網(wǎng)絡(luò)技術(shù)的迅速發(fā)展,開源軟件正以前所未有的優(yōu)勢得以迅速發(fā)展?,F(xiàn)在的開源軟件已經(jīng)成為軟件發(fā)展的主要流行趨勢。開源軟件的成功對軟件產(chǎn)業(yè)起到了巨大的作用。同時,由于目前開源軟件數(shù)量急劇增加,迅速準確地尋找到用戶所需的代碼成為一個關(guān)鍵問題。現(xiàn)有的代碼搜索引擎大都是基于文本的搜索,并未利用語法、語義信息,在搜索準確性方面受到極大限制。因此,有學者提出利用代碼的語法和語義等信息輔助代碼搜索。從多個方面對開源的作用做一個較全面的介紹,并對開源代碼的關(guān)鍵搜索技術(shù)做一個簡要綜述。
關(guān)鍵詞: 開源;復用;搜索;關(guān)鍵詞;語法;語義
0 引言
隨著網(wǎng)絡(luò)時代的來臨和開源運動的發(fā)展,軟件的開發(fā)模式、運行環(huán)境和提供方式都發(fā)生了巨大改變。興起于20世紀90年代的開源軟件取得了巨大成功,其開發(fā)活動具有開放分享、頻繁發(fā)布等特點,能夠有效匯聚軟件各利益相關(guān)方的創(chuàng)意和貢獻,其自由松散的表象下隱藏著重要的軟件工程新理論,對軟件產(chǎn)業(yè)的發(fā)展和格局產(chǎn)生了深遠的影響。目前,開源軟件有著良好的發(fā)展態(tài)勢。開源文化是人類幾千年的智慧結(jié)晶,是一種必然的歷史趨勢,這種發(fā)展趨勢是誰也阻擋不了的。
開源軟件[1]就是在開發(fā)源代碼許可證的規(guī)范下發(fā)布的軟件,以保障用戶自由使用軟件及接觸源代碼的權(quán)利,同時也保障了用戶自行修改、復制以及再分發(fā)的權(quán)利。開源軟件的數(shù)量目前正在不斷大量增長,大量開源軟件的出現(xiàn),對軟件工程的實施起到巨大作用,本文以開源對軟件工程的作用和關(guān)鍵技術(shù)為研究點,主要分析開源對當前軟件工程的作用和針對開源代碼的關(guān)鍵搜索技術(shù)。
1 開源對軟件工程的作用
1.1 基于開源庫的瀏覽學習
數(shù)量巨大的開源庫對于程序員來說是一座巨大的寶藏,源代碼融合了作者數(shù)十年的方法、經(jīng)驗和教訓,對于初學者來說不可多得的學習資源。
對于初學者來說,開源主要有以下兩個方面作用:
?。?)有助于從理論到實踐的平滑過渡。從理論到實踐是一個痛苦的過程,正是因為這種痛苦讓很多初學者望而卻步。
?。?)有助于初學者了解技術(shù)潮流。開源項目往往沒有遺留系統(tǒng)的負擔,比較有利于新技術(shù)和新想法的實現(xiàn)。初學者通過閱讀源碼可以緊跟這些新技術(shù)和新想法。
1.2 開源有助于了解API使用方法
在現(xiàn)代軟件行業(yè)中,越來越多的程序員依靠API庫來完成他們?nèi)粘5拈_發(fā)任務(wù)。HOFFLNANN R[2]等人的研究指出,程序員在軟件開發(fā)的過程中經(jīng)常需要調(diào)用到其他庫里的API。對于一個簡單的API來說,通過一個使用例子,可以更加直觀地看到使用方法,這會讓用戶使用API變得更加快捷方便,省下了閱讀API文檔的過程,提高了開發(fā)效率。
通過示例代碼學習具體API的使用方法是開發(fā)人員進行軟件復用的高效手段。例如,Java程序員要使用排序函數(shù)sort,通常需要打開文檔,找到sort函數(shù),然后仔細查看文檔。這里使用開源代碼的搜索引擎krugle,在開源代碼庫里輸入關(guān)鍵字“sort”,通過對照著搜索結(jié)果中調(diào)用API的方法使用該API,就會省下很多時間,提高開發(fā)效率。
1.3 開源有利于代碼精確復用
代碼復用可以說是任何一個軟件企業(yè)都不能漠視的課題,因為復用已有的代碼意味著開發(fā)人員可以節(jié)省許多對代碼進行測試和提升代碼質(zhì)量的時間。在軟件開發(fā)中,軟件的每個部分幾乎都包括可復用的代碼塊。隨著開源的流行,開源代碼庫的數(shù)量的日益龐大,開源代碼的數(shù)量可以說是不計其數(shù)。如此龐大基數(shù)的代碼幾乎包含了各個方面的代碼??梢哉f很多程序員正在寫或者將要寫的代碼都是代碼庫里已有的代碼,這就浪費了大量的人力、物力。因此,開源就是使得任何所需要的代碼幾乎可以復用。
1.4 開源有助于軟件的推廣
十年前,開源支持者在試圖推廣免費軟件時陷入了困戰(zhàn),推廣實施的障礙包括軟件質(zhì)量、安全保障、后期支持等。然而十年后,開源模式已經(jīng)被大眾接受,相當一部分公司在使用開源軟件,開源甚至更加有助于軟件的推廣[3]。開源已經(jīng)走過了從忽視到嘲笑到打擊到被大家接受的過程[4],究其原因,可以從以下三點來說明:
?。?)注重安全的人更加傾向于開源軟件。開源可以讓大家更加清楚軟件背后到底在做哪些不為人知的事,會讓使用開源軟件的人更加放心。
(2)節(jié)約成本的人更加傾向于開源軟件。在使用軟件時一個不可避免的因素就是用戶是否愿意為其付費。隨著開源軟件的質(zhì)量的提高,用戶更愿意使用一個安全的、高質(zhì)量的、便宜的開源軟件。
(3)開源社區(qū)積攢了大量的人群。在開源代管平臺上發(fā)布項目會發(fā)布得更快,軟件發(fā)布后很快就會被各種用戶使用、轉(zhuǎn)載,形成了一個無形的軟件“供需超市”。開源社區(qū)內(nèi)不同背景、不同專長的人匯集成一股集體的力量,對于開源項目的推廣起到了重要的作用。正如圖1所示,開發(fā)者和用戶通過社區(qū)學習知識、提升能力、提升知名度、擴展人際圈子,企業(yè)通過社區(qū)可以提高企業(yè)知名度、找到合適的人才、推廣技術(shù)和產(chǎn)品、降低成本等,社區(qū)在開源項目的推廣中起到了重要的作用。
1.5 開源有助于軟件的個性化定制
開源軟件能夠迅速推廣得益于個性化定制。個性化定制是用戶介入產(chǎn)品的生產(chǎn)過程,將指定的圖案和文字印刷到指定的產(chǎn)品上,用戶獲得自己定制的個人屬性強烈的商品。
由于開源的關(guān)系,軟件也可以個性化定制。開源意味著任何人都可以去下載修改開源軟件的源碼,制作出屬于自己的專屬軟件版本,而且可以將自己的個性化軟件進行傳播。
以往,軟件給人的思想是“給你什么你就有什么”,大多數(shù)專有軟件公司根據(jù)投資回報比來投資軟件,一些個性化的需求往往得不到他們的重視。然而,開源流行開后,個人或者企業(yè)可以添加自己想要的功能,這種個性化的定制往往使得開源能夠更好地服務(wù)于個人或者企業(yè)。
1.6 開源有助于軟件質(zhì)量的分析
軟件質(zhì)量是軟件產(chǎn)品的靈魂。關(guān)于開源和閉源的軟件質(zhì)量的討論一直沒有停止過。閉源,相對來說,表面上是安全的,因為它的代碼是不公開的,沒有高水平編程能力很難去破解,但它的缺點是本身因開發(fā)人員思路的局限性會有很多漏洞,而自己又不知道,這就給了黑客作惡以可乘之機。
開源軟件由于源碼的開放性,使得用戶和第三方評測者能夠直接通過代碼的分析了解軟件的內(nèi)部質(zhì)量情況,是一種直觀、精確的評測方式。此外,開源軟件能集中群體的力量做到及時發(fā)現(xiàn)漏洞修補漏洞,可以集思廣益發(fā)揮群智群力的作用,讓開源軟件迅速完善起來。
2 源代碼搜索的關(guān)鍵技術(shù)分析
2.1 基于字符串匹配的搜索技術(shù)
2.1.1 基于關(guān)鍵詞的搜索
對源代碼搜索而言,目前絕大多數(shù)的解決方案都可歸類為兩種:一是借助于開源代碼搜索工具或平臺如Github或者Sourceforge等;二是借助于通用搜索引擎。兩者都是基于關(guān)鍵詞的搜索。
在基于關(guān)鍵詞的搜索中,主要采用了布爾搜索模型的搜索策略[5]。在布爾搜索中,用戶的查詢要求用普通的語言敘述,即用戶可完全按照自己的思維習慣提問。其中的查詢要求(條件)A、B…可以分別用若干個標引詞來表示,接著可以用布爾邏輯算符“∨”、“∧”、“?劭”將用戶的提問“翻譯”成系統(tǒng)可以接受的形式。
一般用tk表示標引詞序列,dkn表示與tk有關(guān)的文獻,則tk*={dk1,dk2,…,dkn}就可以用來表示與標引詞tk有關(guān)的文獻全體組成的集合。令Χ(q)表示關(guān)于查詢q的檢出文獻,則:
?。?)q=t,Χ(q)=t*
?。?)q=?劭t,Χ(q)=t*=Dt*
?。?)q=t1∨t2,Χ(q)=t1*∪t2*
?。?)q=t1∧t2,Χ(q)=t1*∩t2*
很明顯,布爾邏輯運算實際上就是集合之間的并、交、補運算,也就是說,布爾邏輯檢索系統(tǒng)實際上是通過對若干個代碼文件集合(代碼文件集D或D的子集)的并、交、補運算回答用戶提問的。
然而,這種方法局限性較大,不能充分利用代碼在語法結(jié)構(gòu)、語義等方面的特性,也無法保證查詢到的代碼與用戶查詢相關(guān)。
2.1.2 基于代碼段的搜索
盡管基于關(guān)鍵詞的搜索也在一定程度上幫助程序員復用源代碼,但是它還是會返回給用戶數(shù)量巨大的搜索結(jié)果,其中包括了很多用戶并不需要的結(jié)果。這是由于基于關(guān)鍵詞的搜索并未區(qū)分搜索的粒度,比如文件、類或者是函數(shù),而僅僅是將匹配到的所有結(jié)果返回給用戶。因此,代碼搜索技術(shù)需要根據(jù)用戶需要返回不同粒度的結(jié)果?;谝褟陀么a的搜索技術(shù)[6]就是返回在過去曾經(jīng)復用過的代碼片段,可以根據(jù)用戶需求返回粒度較小的函數(shù)或者代碼段。
在基于已復用代碼的搜索技術(shù)中,可以認為,過去復用過的代碼很有可能會在將來再次被復用,因此返回給用戶的結(jié)果是在過去被復用過的代碼片段。該方法主要包括了代碼分析部分和代碼搜索部分。代碼分析部分探測將要被返回給用戶的重復代碼片段集合。代碼搜索部分返回給用戶的是與他們輸入相關(guān)的重復代碼片段。利用基于代碼段的搜索方法可以搜索得到更小的粒度,而不僅僅是代碼文件,滿足用戶對于搜索代碼段的需求。
2.1.3 源代碼及時錄入及時搜索參考技術(shù)
據(jù)調(diào)查表明,現(xiàn)代軟件開發(fā)過程,開發(fā)人員大約有19%的工作是在搜索代碼。開發(fā)人員經(jīng)常需要參考Web上的代碼搜索結(jié)果來學習新技術(shù)或者輔助開發(fā)工作[7]。通常情況下,開發(fā)人員需要從IDE或者代碼編輯器切換到瀏覽器,在某個代碼搜索網(wǎng)站例如github上搜索,搜索結(jié)果會出現(xiàn)很多結(jié)果,每個結(jié)果對應(yīng)著一個鏈接,開發(fā)人員不得不一一打開鏈接查看結(jié)果是否滿足需求,十分影響程序員的開發(fā)效率。因此,源代碼實時錄入、實時搜索技術(shù)能夠幫助用戶改善這種狀況。
源代碼即時錄入即時搜索技術(shù)旨在即時找到與用戶輸入代碼片段類似或者相同的代碼段,并將其實時返回給用戶,以幫助用戶學習參考或者復用。源代碼即時錄入即時搜索技術(shù)并非是一種新的代碼搜索技術(shù),它根據(jù)用戶在編輯器中實時輸入的結(jié)果,來搜索和當前用戶輸入的代碼類似的代碼片段返回給用戶,輔助用戶進行開發(fā)。
2.2 基于語法的源代碼搜索技術(shù)
2.2.1 利用程序結(jié)構(gòu)的搜索方法
與網(wǎng)頁文件搜索相比,代碼文件有著自己的特點,而在傳統(tǒng)代碼搜索中還只是利用關(guān)鍵字進行搜索,忽略代碼本身的特性,因此,有研究人員提出了基于程序結(jié)構(gòu)的源代碼搜索。
在結(jié)構(gòu)化程序設(shè)計方法中,任何程序都可以用三種基本結(jié)構(gòu)(順序結(jié)構(gòu)、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu),如圖2所示)來表示,可以利用其程序結(jié)構(gòu)輔助搜索。
一方面,根據(jù)用戶的查詢輸入,生成所需的程序結(jié)構(gòu)的特征向量,這些結(jié)構(gòu)特征包括:順序結(jié)構(gòu)數(shù)、分支結(jié)構(gòu)數(shù)、循環(huán)結(jié)構(gòu)數(shù)等。另一方面,分析出開源庫中的源代碼文件,得到程序結(jié)構(gòu)的特征向量,并建立數(shù)據(jù)庫。若兩個向量的相似度達到一定值,則說明該向量對應(yīng)的代碼與用戶所需的程序結(jié)構(gòu)相似,將其返回給用戶。
2.2.2 利用控制流圖的搜索方法
隨后又有研究人員提出利用控制流圖輔助搜索。在結(jié)構(gòu)化程序設(shè)計方法中,程序是一系列過程的集合,而控制流圖是表示一個過程內(nèi)所有基本快執(zhí)行的可能流向和每個基本塊所對應(yīng)的語句表,能反映一個過程的實時執(zhí)行過程。因此,利用控制流圖來輔助搜索可以幫助提高精確度。
在該搜索方法中,每個源代碼由一個控制流圖來表達,每一個節(jié)點表示一個基本塊。利用從用戶輸入得到的信息,系統(tǒng)生成一個控制流圖,如果兩個控制流圖是同構(gòu)的,則可以認為該控制流圖對應(yīng)的代碼即為用戶要搜索的結(jié)果[8]。例如圖3(a)中的代碼可以生成圖3(b)所示的控制流圖。
但是在利用控制流圖的搜索方法中,用戶需要輸入一個控制流圖,這無疑加重了用戶的使用負擔,如何根據(jù)用戶簡單的輸入自動生成控制流圖值得研究。
2.2.3 利用程序語法樹的搜索方法
在2.2.1中,利用程序結(jié)構(gòu)進行代碼搜索,然而Sourcerer[9]等搜索引擎比較簡單粗糙地利用程序結(jié)構(gòu)信息(比如if語句的個數(shù)、for循環(huán)結(jié)構(gòu)的個數(shù)等)能使搜索結(jié)果精確一些,但是并沒有深入全面地利用語法信息來輔助代碼搜索,而本文可以利用程序語法樹來輔助代碼搜索。
語法樹是程序代碼的樹狀表示,它是形式化、規(guī)范化的程序語義表示,是程序設(shè)計者思想的形式化表示。語法樹是程序的編譯或者解釋過程中的一個中間數(shù)據(jù)結(jié)構(gòu),處于源代碼和中間語言代碼之間。源代碼太具體,中間語言代碼又過于抽象,而語法樹介于兩者之間,能夠形象地抽象出程序的結(jié)構(gòu)信息,為代碼的搜索提供更加準確、全面的信息。例如如下代碼:
if(x==2){
x=a+b;
}
這段代碼的語法樹如圖4所示。
黃麗韶等人[10]在Sourcerer的經(jīng)驗上進行了基于程序語法樹的源代碼搜索的研究,從語法結(jié)構(gòu)角度提出一種源代碼的搜索方法,構(gòu)造基于語法結(jié)構(gòu)的代碼過濾器,通過遍歷抽象語法樹來抽取源代碼的信息建立索引。
2.3 基于語義的源代碼搜索技術(shù)
2.3.1利用功能需求的源代碼搜索方法
1998年夏威夷大學的Woods等人提出了基于需求的代碼搜索方法,通過建立代碼的抽象數(shù)據(jù)描述來建立索引,之后通過一種需求描述(Plan)語言來描述軟件的功能需求。通過需求描述語言對功能需求的詳細描述,可以全面地得到各個功能的具體實現(xiàn)方式,代碼搜索引擎將該需求描述和代碼庫中的抽象數(shù)據(jù)描述進行匹配,得到匹配后的代碼,通過一定的排序和過濾方式,實現(xiàn)了基于需求的搜索方法。該方法搜索的輸入比較繁雜,需要用戶給出各個過程的實現(xiàn)方法,使用起來會比較復雜。
2.3.2 基于測試的源代碼搜索方法
基于測試的源代碼搜索(TDCS)[11]是以測試用例作為用戶搜索的輸入來進行搜索的一種源代碼搜索方法。由于測試用例可以用來描述系統(tǒng)中缺失的特征,因此測試用例對于代碼搜索來說能夠提供更多的語義信息,也會讓代碼搜索結(jié)果更加準確。
TDCS確保測試用例描述了要被搜索的代碼的特征。在TDCS中,測試用例被設(shè)計用來描述系統(tǒng)中缺失的特征。開發(fā)人員通過測試用例來搜索結(jié)果,該方法會根據(jù)測試用例來構(gòu)造出用戶的查詢輸入,根據(jù)該查詢輸入在開源庫中進行搜索,然后,將搜索得到的結(jié)果編織進自己的代碼中。
2.3.3 基于輸入輸出的源代碼搜索方法
KATHRYN S[12]提出了一種新的代碼搜索方法,基于輸入輸出來進行源代碼搜索。利用該方法,程序設(shè)計者只需編寫輕量級的需求描述來定義輸入和期望的輸出。與現(xiàn)有的搜索不同的是,該方法利用SMT(Satisfiability Modulo Theories)求解,對設(shè)計者提供的描述采用符號分析,自動轉(zhuǎn)換為匹配的約束,從而在代碼倉庫中識別程序或程序片段。
整套方法的核心在于:對代碼倉庫在獨立于用戶查詢的情況下進行了離線的信息索引,索引使用獨特的符號分析,將程序的語義和描述其行為的約束進行映射。
2.4 其他源代碼搜索方法
2.4.1 利用程序員行為輔助搜索
程序員始終是軟件開發(fā)活動的主體,無論哪種源代碼搜索方法,都離不開程序員,對程序員習慣進行調(diào)查有助于改進搜索方法和搜索體驗。通過研究程序員習慣,然后填補程序員搜索活動細節(jié),能夠輔助源代碼搜索技術(shù),幫助解決程序員搜索代碼面臨的困難。
例如在沈玲等人[13]對于程序員搜索習慣的研究中發(fā)現(xiàn),程序員一般搜索范圍都很廣,產(chǎn)生很多不相關(guān)的結(jié)果?;谒麄兊挠^察,如果能在返回結(jié)果中包含上下文的信息將是非常有價值的。因此,在代碼搜索時,如果能在搜索結(jié)果中提供上下文的信息,這將能讓程序員更快地做出是否相關(guān)的判斷。
2.4.2 基于語法結(jié)構(gòu)和輸入輸出的搜索方法
要提高代碼搜索的精度,不僅要從代碼的表層字符串含義入手,還要挖掘代碼的功能結(jié)構(gòu)和語義信息,這也是當前代碼搜索的難點。通過分析語法樹和代碼的輸入輸出可以得到非常豐富的信息,進而提高代碼搜索的精度。由此產(chǎn)生了結(jié)合語法結(jié)構(gòu)和輸入輸出的搜索方法。
該方法通過分析語法樹得到代碼的邏輯結(jié)構(gòu)特征,通過分析源代碼的輸入和輸出信息得到程序的語義功能。將語法與語義信息結(jié)合起來,可以提高搜索的精度。該方法結(jié)合了語法語義信息,為代碼搜索方法提供了新的思路。
3 結(jié)論
開源軟件正在席卷全球,根據(jù)Black Duck公司提供的數(shù)據(jù),在過去的一年中,他們統(tǒng)計了5 000個有開源項目的網(wǎng)址,包括了1 000億源代碼行,發(fā)現(xiàn)開源項目的數(shù)目已經(jīng)翻了一番。
傳統(tǒng)的基于關(guān)鍵字的源代碼搜索方法已經(jīng)不能滿足人們的需求,由此產(chǎn)生了各種其他的代碼搜索方法,希望更快更好地幫助用戶找到高質(zhì)量代碼。然而目前的源代碼搜索引擎大都是基于文本的搜索,沒有利用代碼在語法、語義等上的特性,在搜索準確性方面受到極大的限制。針對這些現(xiàn)有流行的源代碼搜索引擎存在的問題已經(jīng)有越來越多的學者投入了該領(lǐng)域的研究。未來筆者也會繼續(xù)深入研究開源的相關(guān)技術(shù)。
參考文獻
[1] 徐哲,蔡建平.基于開源軟件的軟件工程實施系統(tǒng)研究[J].微計算機信息,2009,25(9):178-180.
[2] HOFFLNANN R, FOGARTY J, WELD D S. Assieme: finding and leveraging implicit references in a web search interface for programmars In proceedings of the 20th annual AC symposium on User interface software and technology[C]. Newport, Rhode Island, USA, 2007:13-22.
[3] 熊瑞萍,萬江平.開源軟件的突圍之路——關(guān)于開源運動的若干思考[J].科技管理研究,2009(3):252-255.
[4] 謝世誠.“開源十杰”Michael Tiemann來華開博客[J].微型機與應(yīng)用,2007,26(11):22.
[5] 劉紅泉,張亮峰.布爾邏輯檢索模型的分析探討[J].現(xiàn)代情報,2004(9):4-6.
[6] ISHIHARA T, HOTTA K, HIGO Y, et al. Reusing reused code[J]. WCRE 2013, Koblenz, Germany: ERA-Track,457-461.
[7] 陸晨.一種基于Web資源的代碼范例搜索工具[J].科技資訊,2011(33):23-25.
[8] BAJRACHARYA S, NGO T, LINSTEAD E, et al. Sourcerer: a search engine for open source code supporting structure-based search[C]. Proceedings of International Conference on Object-Oriented Programming, 2006:25-26.
[9] 陳新.基于程序控制流圖源代碼相似程度分析系統(tǒng)[J].計算機系統(tǒng)應(yīng)用,2013,22(3):144-147.
[10] 黃麗韶.基于語法結(jié)構(gòu)的源代碼搜索的研究[J].電腦與電信,2013(5):30-33,39.
[11] LAZZARINI LEMOS O A, CARVALHO de P A, KONISHI G. Using thesaurus-based tag clouds to improve test-driven code search[J]. VII Brazilian Symposium on Software Components, 2013,46(1):99-108.
[12] STOLEE K T, ELBAUM S, DOBOS D. Solving the search for source code[J]. ACM Transactions on Software Engineering and Methodology,2014,23(3):1-45.
[13] 沈玲,黃熹,李艷陽.程序員搜索習慣的研究及對搜索工具開發(fā)的啟示[J].中國高新技術(shù)企業(yè),2012(27):27-30.