国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

程序理解:現(xiàn)狀與未來*

2019-03-01 10:42:32芝,劉芳,李
軟件學(xué)報(bào) 2019年1期
關(guān)鍵詞:代碼語義程序

金 芝,劉 芳,李 戈

1(北京大學(xué) 信息科學(xué)技術(shù)學(xué)院,北京 100871)

2(高可信軟件技術(shù)教育部重點(diǎn)實(shí)驗(yàn)室(北京大學(xué)),北京 100871)

程序理解是軟件工程中的一個(gè)經(jīng)典話題,又叫作軟件理解或系統(tǒng)理解.自軟件出現(xiàn)以來,甚至在軟件工程提出之前,就有了程序理解這一問題.1968年第 1次軟件工程研討會(huì)之后,程序理解成為軟件工程中的關(guān)鍵活動(dòng),在進(jìn)行軟件重用、維護(hù)、遷移、逆向工程以及軟件系統(tǒng)擴(kuò)展等任務(wù)時(shí),都要依賴于對(duì)程序的理解[1].比如,源碼逆向工程通過分析目標(biāo)系統(tǒng)來識(shí)別系統(tǒng)的成分及其相互關(guān)系,創(chuàng)建系統(tǒng)的更高抽象層次上的表示,包括構(gòu)建目標(biāo)系統(tǒng)的概念模型、抽取程序結(jié)構(gòu)和控制信息以及進(jìn)行數(shù)據(jù)抽取和系統(tǒng)抽象.程序理解是軟件逆向工程的主要實(shí)現(xiàn)手段和行為活動(dòng),貫穿整個(gè)軟件逆向工程,是決定軟件逆向工程成敗的關(guān)鍵[2].在軟件維護(hù)和演化中,例如軟件適應(yīng)(adaptive)、軟件修復(fù)(corrective)、軟件復(fù)用(reuse)等任務(wù),程序理解也是其首要活動(dòng),其他活動(dòng)都是在程序理解的基礎(chǔ)上進(jìn)行的.例如:完成軟件適應(yīng)任務(wù)的流程包括理解系統(tǒng)、定義適應(yīng)需求、制定適應(yīng)策略、設(shè)計(jì)、代碼修改、調(diào)試、回歸測(cè)試;軟件修復(fù)任務(wù)的流程包括理解系統(tǒng)、提出/評(píng)估問題假設(shè)、修復(fù)代碼、回歸測(cè)試.隨著程序設(shè)計(jì)語言的不斷變化和軟件復(fù)雜性的不斷提高,程序理解一直面臨著挑戰(zhàn),新的研究問題不斷涌現(xiàn).

什么是“程序理解”呢?首先看看什么是“理解”.在 Wikipedia中,“理解(comprehension或 understanding)”(https://en.wikipedia/wiki/Comprehension)是指與抽象或物理對(duì)象相關(guān)的心理過程,比如:理解一個(gè)人、一件事或一段話,就是建立理解的主體和這個(gè)人、這件事或這段話之間的關(guān)系,表明這個(gè)主體能夠想象出這個(gè)對(duì)象(具有心理表征),并且/或者能用一些概念恰當(dāng)?shù)乜坍嬤@個(gè)對(duì)象(https://en.wikipedia/wiki/Understanding).可以看出:理解是和學(xué)習(xí)相關(guān)的活動(dòng),需要建立從理解的對(duì)象所屬的概念域到理解的主體所熟悉的概念域的(概念)映射.

從學(xué)習(xí)和認(rèn)知的角度,可以把程序理解和自然語言文本理解進(jìn)行類比.自然語言文本是用自然語言表述的一種認(rèn)知,閱讀和理解自然語言文本,就是從文本中獲取知識(shí)的過程.程序通??醋魇怯贸绦蛟O(shè)計(jì)語言表述的一種認(rèn)知,因此可以抽象地把程序理解解釋為從程序中獲得關(guān)于程序所表達(dá)的知識(shí)的過程.與自然語言理解的語法、語義和語用等理解階段相比較,程序理解可分為側(cè)重文法理解的語法層上的程序分析、側(cè)重抽象語義(如信息流、控制流、抽象解釋等)提取的語義層上的程序分析以及側(cè)重程序動(dòng)態(tài)語義的程序行為分析.這體現(xiàn)了程序理解技術(shù)和結(jié)果的由淺入深的層次劃分.

從方法和技術(shù)的角度,程序理解以程序分析為基礎(chǔ).通過對(duì)程序進(jìn)行人工或自動(dòng)分析,以驗(yàn)證、確認(rèn)或發(fā)現(xiàn)軟件性質(zhì).程序分析貫穿于軟件開發(fā)、維護(hù)和復(fù)用階段:在開發(fā)階段,對(duì)正在開發(fā)的程序進(jìn)行分析,以快速、高效地開發(fā)出高質(zhì)量的軟件;在維護(hù)階段,對(duì)已經(jīng)開發(fā)、部署或運(yùn)行的程序進(jìn)行分析,以準(zhǔn)確理解并維護(hù)該程序,從而使其能夠提供更好的服務(wù);在復(fù)用階段,對(duì)之前開發(fā)的程序進(jìn)行分析,以復(fù)用其中有價(jià)值的成分.上述不同階段的程序分析過程差異較大,需要的分析技術(shù)也各有不同.根據(jù)其分析過程是否需要運(yùn)行程序,可以將程序分析分為靜態(tài)分析和動(dòng)態(tài)分析:靜態(tài)分析不需要運(yùn)行程序,直接對(duì)程序源代碼進(jìn)行分析,獲取相關(guān)信息[3,4];動(dòng)態(tài)分析則是分析程序運(yùn)行時(shí)性質(zhì)[5],通過程序的運(yùn)行獲取程序的輸入/輸出關(guān)系或程序內(nèi)部狀態(tài)等,以驗(yàn)證或發(fā)現(xiàn)程序的性質(zhì).

從工程應(yīng)用的角度看,程序理解主要用于軟件開發(fā)過程中涉及已有軟件制品及其使用和變更的活動(dòng).比如:軟件復(fù)用需要將已有軟件制品用于當(dāng)前軟件開發(fā);軟件逆向工程從已有軟件制品中獲取該軟件制品的高層抽象,所謂“逆向”是針對(duì)自頂向下的軟件開發(fā)過程而言的;軟件演化則在認(rèn)識(shí)到當(dāng)前軟件已經(jīng)不適合新的場(chǎng)景時(shí),需要進(jìn)行適當(dāng)?shù)能浖{(diào)整和變更.在進(jìn)行這些軟件工程任務(wù)時(shí),需要理解當(dāng)前軟件制品的含義,包括它所表達(dá)的軟件能力及其實(shí)現(xiàn)方式,等等.

已有的工作從各自的研究側(cè)重點(diǎn)出發(fā),給出了程序理解的不同的說法.一些典型的說法比如:

· 程序理解是根據(jù)軟件源代碼去理解程序的過程[6];

· 程序理解的任務(wù)是構(gòu)建軟件的從代碼模型到應(yīng)用領(lǐng)域問題間各抽象層次上的模型,目的是支持軟件維護(hù)、演化和再工程[7];

· 程序理解是利用領(lǐng)域知識(shí)以及語法語義知識(shí)來理解軟件制品,構(gòu)建軟件制品與使用場(chǎng)景之間的心理認(rèn)知模型(區(qū)別于物理模型)的過程[8];

· 程序理解是通過研究諸如源代碼和文檔等制品來理解軟件系統(tǒng)內(nèi)部工作原理,為軟件維護(hù)任務(wù)提供足夠的信息[9];

· 程序理解是理解整個(gè)軟件系統(tǒng)或部分軟件系統(tǒng)如何運(yùn)行的活動(dòng)[10];

· 程序理解的任務(wù)是解釋軟件行為,通常是通過閱讀源代碼,來判斷它的作用和代碼如何與整個(gè)軟件進(jìn)行交互[11].

當(dāng)前,云計(jì)算和人機(jī)物融合應(yīng)用模式不斷涌現(xiàn),加速了社會(huì)的信息化進(jìn)程,使軟件成為一種社會(huì)基礎(chǔ)設(shè)施.軟件的可成長(zhǎng)性和可持續(xù)演化性成為軟件工程的重要關(guān)注點(diǎn)[12].圖靈獎(jiǎng)得主Sifaki教授曾指出,(軟件)系統(tǒng)工程的關(guān)注點(diǎn)正在發(fā)生轉(zhuǎn)變,體現(xiàn)為:(1) 從小規(guī)模集中式不可進(jìn)化的系統(tǒng),到大型分布式可演化的系統(tǒng);(2) 從嚴(yán)格控制的系統(tǒng)與外部環(huán)境的交互,到不可預(yù)測(cè)的動(dòng)態(tài)變化環(huán)境;(3) 從設(shè)計(jì)正確性到通過適應(yīng)性確保正確性[13].軟件具有可成長(zhǎng)和可持續(xù)演化能力的基本條件,是軟件的可理解性甚至軟件的可自我認(rèn)知性.另一方面,軟件自適應(yīng)性和軟件智能化等研究熱點(diǎn)的形成,感知軟件運(yùn)行狀態(tài)和運(yùn)行環(huán)境,以及以此為基礎(chǔ)的運(yùn)行時(shí)決策和系統(tǒng)適應(yīng)性變更和持續(xù)演化,已經(jīng)成為研究的主要關(guān)注點(diǎn),這更強(qiáng)調(diào)了運(yùn)行時(shí)系統(tǒng)的可理解性將成為亟待解決的問題.

因此,軟件(程序)理解,特別是軟件的自理解和自認(rèn)知,已經(jīng)被提到了前所未有的重要高度,有必要重新審視軟件理解的內(nèi)涵,分析目前的技術(shù)手段,結(jié)合系統(tǒng)工程的發(fā)展探索其新的需求,從而展望未來的技術(shù)挑戰(zhàn)和趨勢(shì).本文首先通過文獻(xiàn)分析展示長(zhǎng)期以來軟件工程領(lǐng)域?qū)Τ绦蚶斫獾难芯坎季?進(jìn)而分別從學(xué)習(xí)和認(rèn)知的角度、方法和技術(shù)的角度以及軟件工程應(yīng)用的角度這 3個(gè)問題,綜合分析程序理解研究的發(fā)展脈絡(luò)和研究進(jìn)展,最后,根據(jù)軟件系統(tǒng)的發(fā)展趨勢(shì)探討程序理解面臨的挑戰(zhàn)和發(fā)展趨勢(shì).

1 程序理解研究關(guān)注度分析

考察研究人員對(duì)程序理解研究方向的關(guān)注度,有一個(gè)維度是查看發(fā)表文章的強(qiáng)度.我們用“程序理解”/ “軟件理解”等關(guān)鍵詞在 IEEE Xplore Digital Library上檢索近年來發(fā)表的文獻(xiàn).使用程序理解(program comprehension)作為關(guān)鍵詞,檢索到 2 124篇文章;使用軟件理解(software comprehension)作為關(guān)鍵詞,檢索到2 115篇文章.這兩個(gè)關(guān)鍵詞的檢索結(jié)果有很大部分是重合的.從檢索結(jié)果中的文獻(xiàn)來看,1985年之前發(fā)表的文章數(shù)目較少,因此我們從1985年之后發(fā)表的文獻(xiàn)開始統(tǒng)計(jì).對(duì)總共4 139個(gè)檢索結(jié)果進(jìn)行人工篩選,去掉重合的文獻(xiàn),并通過人工閱讀文章標(biāo)題、文章摘要和關(guān)鍵詞,選取出與程序理解的具體任務(wù)和理解技術(shù)相關(guān)的文獻(xiàn)共136篇.對(duì)它們從文獻(xiàn)發(fā)表年代、研究主題分布以及研究主題各年代分布等幾個(gè)維度進(jìn)行了統(tǒng)計(jì),得到如圖1所示的分布結(jié)果.可以看出:

(1) 自1985年起,對(duì)程序理解研究的關(guān)注度一直處于上升趨勢(shì)(如圖1(a)所示);

(2) 軟件維護(hù)任務(wù)和程序理解最相關(guān),研究工作占有很大份額;其次是文檔分析、重構(gòu)和生成以及逆向工程(如圖1(b)所示);

(3) 機(jī)器學(xué)習(xí)和深度學(xué)習(xí)技術(shù)近年來大量進(jìn)入程序理解領(lǐng)域(如圖1(c)所示);

(4) 文獻(xiàn)所報(bào)道的研究主題完整地覆蓋了程序理解研究的3個(gè)方面(如圖1(c)所示).

a.比如數(shù)據(jù)挖掘、特征提取、機(jī)器學(xué)習(xí)和深度學(xué)習(xí)等,是具有代表性的程序理解技術(shù).其中,機(jī)器學(xué)習(xí)、特征提取、深度學(xué)習(xí)的程序理解方法,是最近10年出現(xiàn)的,并正日漸成為前沿?zé)狳c(diǎn);

b.對(duì)程序的語法分析、語義理解和程序的動(dòng)態(tài)行為分析,表現(xiàn)了程序理解的認(rèn)知層次.值得注意的是:程序語法分析的研究在1995年后出現(xiàn),程序語義理解和運(yùn)行行為分析的工作在 2000年后出現(xiàn),表現(xiàn)了程序理解從語法到語義再到語用的認(rèn)知不斷深入的過程;

c.軟件維護(hù)、逆向工程、文檔重構(gòu)和生成、軟件測(cè)試、代碼缺陷檢測(cè)和代碼克隆等軟件工程的經(jīng)典任務(wù),是程序理解的主要應(yīng)用場(chǎng)景,除了軟件測(cè)試和逆向工程外,應(yīng)用熱度一直處于上升趨勢(shì).

除此之外,本文還根據(jù)程序理解相關(guān)會(huì)議的投稿論文數(shù),展示該領(lǐng)域的研究關(guān)注度,包括統(tǒng)計(jì)軟件工程頂級(jí)會(huì)議 ICSE(Int’l Conf.on Software Engineering)近幾年來各個(gè)主題提交文章數(shù)以及程序理解會(huì)議 ICPC(Int’l Conf.on Program Comprehension)近10年來錄用文章數(shù).其中,圖2展示了ICSE 2015~2018各個(gè)主題的提交情況,列出了提交文章數(shù)排名前十的主題情況(2015年和2017年未設(shè)置實(shí)證軟件工程這個(gè)主題,2017年未設(shè)置軟件工程的人為和社會(huì)因素這個(gè)主題).其中,軟件測(cè)試、程序分析、軟件演化與維護(hù)、軟件調(diào)試、錯(cuò)誤定位和修復(fù)等主題與程序理解密切相關(guān)(用藍(lán)色色系表示),這幾個(gè)主題的文章數(shù)目一直占全部文章數(shù)的很大份額.可見,程序理解在軟件工程領(lǐng)域中占據(jù)著重要的地位.

Fig.1 Statistical analysis of program comprehension literature圖1 程序理解研究論文的統(tǒng)計(jì)分析

Fig.2 Top ten topics in the submissions of ICSE from 2015 to 2018圖2 2015年~2018年ICSE提交文章數(shù)目前十的主題及其提交文獻(xiàn)數(shù)目

ICPC是專門以程序理解為主題的國(guó)際會(huì)議,該會(huì)議平均每年大概錄用40篇文獻(xiàn),近10年來的錄用文章數(shù)如圖3所示,整體呈緩慢上升趨勢(shì).這表明,程序理解相關(guān)研究在近10年來一直都是較為熱門的話題,可以推測(cè),程序理解在未來仍然會(huì)是活躍的研究主題.

Fig.3 Number of accepted papers of ICPC in recent ten years圖3 ICPC近10年錄用文章數(shù)目統(tǒng)計(jì)

2 程序理解的認(rèn)知過程、技術(shù)方法和工程應(yīng)用

2.1 從認(rèn)知過程看程序理解

程序理解本身就是一個(gè)學(xué)習(xí)和認(rèn)知的過程.程序是知識(shí)的編碼,程序理解是指從程序中學(xué)習(xí)程序所表達(dá)的領(lǐng)域知識(shí)的過程.根據(jù)構(gòu)建式學(xué)習(xí)的理論,學(xué)習(xí)和認(rèn)知的過程是面向目標(biāo)或模型驅(qū)動(dòng)的歸納抽象過程:第一,學(xué)習(xí)是學(xué)習(xí)者個(gè)體從學(xué)習(xí)材料中通過提取或抽象等手段構(gòu)建知識(shí)體的過程;第二,所構(gòu)建的知識(shí)體除了依賴學(xué)習(xí)材料,很大程度上還依賴于學(xué)習(xí)者已有的知識(shí)背景和該次學(xué)習(xí)的目的.

早期很多對(duì)程序理解的探討,都是從認(rèn)知的角度出發(fā)進(jìn)行的,它們大都側(cè)重于研究程序員的學(xué)習(xí)過程和知識(shí)的構(gòu)建過程.從構(gòu)建式學(xué)習(xí)理論出發(fā),可以有兩種基本的程序理解策略.

· 自底向上的策略[1]:這種策略將程序理解看作是一個(gè)逐層聚合的過程.也就是從閱讀程序源碼開始,將這些源碼中包含的信息逐層組合、抽象成更高層次的信息.例如,一種程序認(rèn)知框架區(qū)分語法和語義兩個(gè)層次:語法層關(guān)注程序的語句和基本單元;語義層與程序語言無關(guān),是逐層抽象直到所抽象的知識(shí)能夠描述應(yīng)用領(lǐng)域[14].另一種認(rèn)知框架區(qū)分程序模型(program model)和情景模型(situation model):程序模型對(duì)程序的控制流進(jìn)行抽象;情景模型則是封裝了關(guān)于數(shù)據(jù)流抽象和功能抽象的知識(shí),表達(dá)了程序的目標(biāo)層次[15].用傳統(tǒng)的軟件開發(fā)方式可以解釋這種策略背后的原因,即,程序理解是為了還原自底向上的軟件開發(fā)過程;

· 自頂向下的策略[1]:這種策略將程序理解看作是重新組織程序員自身已有的關(guān)于程序應(yīng)用領(lǐng)域的知識(shí),并建立這些知識(shí)到程序源碼上的映射.比如,一個(gè)典型的過程是:從關(guān)于領(lǐng)域應(yīng)用的假設(shè)出發(fā),根據(jù)已有的領(lǐng)域知識(shí)進(jìn)行逐層分解,同時(shí)與程序源碼進(jìn)行比對(duì)或驗(yàn)證,從而建立假設(shè)和源代碼之間的關(guān)聯(lián).這種方式體現(xiàn)了模型驅(qū)動(dòng)的思想,亦即:如果模型存在,程序理解就是將具體的程序片段關(guān)聯(lián)到已知的模型上,通過模型的結(jié)構(gòu)和語義去刻畫程序的結(jié)構(gòu)和語義.

對(duì)復(fù)雜一點(diǎn)的程序而言,僅僅只采用一種策略是不可行的,這兩種策略常常需要結(jié)合起來交替地使用,因而產(chǎn)生了集成的策略.

· 集成式程序理解模型[16]:集成式程序理解模型結(jié)合了自底向上和自頂向下的策略,它認(rèn)為:對(duì)比較熟悉的代碼,可以采用自頂向下的方式進(jìn)行理解,直接建立源碼和應(yīng)用知識(shí)之間的關(guān)聯(lián);而對(duì)不太熟悉的代碼,則需要采用自底向上的策略從底層開始進(jìn)行逐層抽象,以獲得程序所表達(dá)的領(lǐng)域知識(shí).比如,von Mayrhauser等人提出的集成式程序理解模型涉及4個(gè)成分.

(1) 自頂向下的策略:從領(lǐng)域知識(shí)出發(fā)產(chǎn)生假設(shè),并不斷細(xì)化假設(shè),直到假設(shè)能關(guān)聯(lián)到熟悉的代碼片段上;

(2) 構(gòu)建程序模型:從未知代碼出發(fā)試圖理解其控制流;

(3) 構(gòu)建情景模型:從已構(gòu)建的程序模型出發(fā),發(fā)現(xiàn)數(shù)據(jù)流,得出功能抽象;

(4) 領(lǐng)域知識(shí):包含程序員已經(jīng)掌握的關(guān)于應(yīng)用領(lǐng)域、應(yīng)用目標(biāo)、程序語言等的知識(shí),用于支持其中的推理過程.

這些早期研究結(jié)果的獲得,得益于對(duì)程序員認(rèn)知過程的實(shí)驗(yàn)研究.這些實(shí)驗(yàn)性工作的目的是:研究程序員如何理解程序,進(jìn)而找到能夠幫助程序員理解程序或者提高理解效率的方式.這類實(shí)驗(yàn)工作一般采用諸如內(nèi)省法(有聲思維法)、記憶測(cè)試法等認(rèn)知心理學(xué)的方法.比如,文獻(xiàn)[17]中的有聲思維法的實(shí)驗(yàn)顯示:程序員在遇到熟悉的領(lǐng)域時(shí),首先陳述領(lǐng)域假設(shè)(自頂向下法);而當(dāng)遇到不熟悉的領(lǐng)域時(shí),要結(jié)合源碼作推斷(自底向上法).文獻(xiàn)[16]中的有聲思維法實(shí)驗(yàn)也證實(shí):程序員在理解比較大的軟件系統(tǒng)的源碼時(shí)會(huì)涉及多個(gè)不同的策略,用到多種模型,在理解的過程中經(jīng)常在不同策略和不同模型之間切換(集成式方法).

記憶測(cè)試實(shí)驗(yàn)則希望展示源碼理解和源碼記憶之間的關(guān)系.文獻(xiàn)[18]的記憶測(cè)試實(shí)驗(yàn)顯示:按可執(zhí)行過程排序的源碼,比亂序源碼更容易記憶.文獻(xiàn)[19]中的實(shí)驗(yàn)發(fā)現(xiàn):有經(jīng)驗(yàn)的程序員主要是依靠命名慣例進(jìn)行理解和記憶,當(dāng)碰到不熟悉的命名方式時(shí)也和新手一樣沒有頭緒.還有實(shí)驗(yàn)表明:當(dāng)程序語句之間具有邏輯性時(shí),程序員的反應(yīng)更快[15].這些實(shí)驗(yàn)性研究都表明,源碼的可理解性和可記憶性是正相關(guān)的.

這些關(guān)于程序可理解性的實(shí)驗(yàn)研究,在一定程度上引出了集成式開發(fā)環(huán)境的設(shè)計(jì).比如,大部分IDE采用的縮進(jìn)格式、合適的字符間隔寬度、用顏色標(biāo)定不同類型的語句等策略,它們都是為了提高程序可理解性而引入的編程布局上的考慮[20].

高級(jí)語言以及 API和領(lǐng)域特定語言(DSLs)也與這些早期程序理解研究同步發(fā)展.高級(jí)語言的出現(xiàn)和發(fā)展,對(duì)不斷提升程序的可理解性起到重要的作用,方便了軟件開發(fā)、軟件重用、軟件系統(tǒng)逆向工程和系統(tǒng)演化等.

值得注意的是:沉寂了多年的程序可理解性的實(shí)驗(yàn)研究,由于新的實(shí)驗(yàn)技術(shù)的出現(xiàn),近年來又重新引起了學(xué)術(shù)界和工業(yè)界關(guān)于程序理解作為認(rèn)知過程研究的關(guān)注.比如,研究者們利用功能磁共振成像、近紅外光譜學(xué)、腦電圖等實(shí)驗(yàn)手段,觀察程序員在理解程序的過程中腦部區(qū)域的激活或活躍狀態(tài),試圖建立不同的激活區(qū)域與編程任務(wù)的難度之間的相關(guān)性[21-23].

2.2 程序理解的方法

從程序理解方法的角度,現(xiàn)有工作可以分為基于分析的方法和基于學(xué)習(xí)的方法.

· 基于分析的方法以是否需要運(yùn)行軟件為準(zhǔn)則,又可以分為靜態(tài)分析方法和動(dòng)態(tài)分析方法[24].

? 靜態(tài)程序理解直接分析程序源代碼,從中獲取相關(guān)信息,分析過程不需要執(zhí)行程序[3,4].由于其不必運(yùn)行系統(tǒng),因而可進(jìn)行系統(tǒng)的早期分析,在系統(tǒng)開發(fā)階段就可以開始,分析結(jié)果具有普適性,也可以覆蓋所有可能的執(zhí)行路徑;

? 動(dòng)態(tài)程序理解主要理解程序運(yùn)行時(shí)性質(zhì)[5],它通過執(zhí)行程序,獲取其輸入輸出關(guān)系或內(nèi)部狀態(tài)等,提取軟件的性質(zhì).與靜態(tài)方法相比,其特點(diǎn)是需要運(yùn)行系統(tǒng),通常需要具體的輸入數(shù)據(jù),因?yàn)橛芯唧w數(shù)據(jù),其分析結(jié)果更為精確;但反過來,因?yàn)榻Y(jié)果的精確是對(duì)特定輸入而言的,不能保證分析結(jié)果對(duì)其他輸入也適用,因此不具有普適性.

· 近年來,數(shù)據(jù)挖掘和機(jī)器學(xué)習(xí)技術(shù)在多個(gè)領(lǐng)域獲得成功,特別是深度學(xué)習(xí)在圖像處理、語音識(shí)別、自然語言處理等領(lǐng)域的多項(xiàng)任務(wù)上取得的成功.在軟件工程領(lǐng)域,由于開源代碼的大量出現(xiàn),軟件工程數(shù)據(jù)越來越容易獲取,基于學(xué)習(xí)的技術(shù)近年來也開始得到關(guān)注.許多研究者利用數(shù)據(jù)挖掘、機(jī)器學(xué)習(xí)等技術(shù)進(jìn)行程序理解,從源代碼和代碼文檔中獲取信息.深度學(xué)習(xí)技術(shù)越來越多地應(yīng)用于程序理解,成為一種數(shù)據(jù)驅(qū)動(dòng)的端到端的程序理解方法.

2.2.1 基于靜態(tài)分析的程序理解

程序靜態(tài)分析由M.E.Fagan于1976年提出[25],主要通過分析程序源碼以發(fā)現(xiàn)其中的錯(cuò)誤.Fagan于1976年發(fā)表的文獻(xiàn)[25]提到,使用靜態(tài)分析技術(shù)發(fā)現(xiàn)了 30%~70%的邏輯和編碼錯(cuò)誤.后來,程序靜態(tài)分析成為程序理解的重要方面.

按照理解的層次,程序靜態(tài)分析可分為語法分析和語義分析.程序語法分析按照編程語言的語法和詞法規(guī)則對(duì)程序源碼進(jìn)行分析,可以檢查程序在語法上是否符合預(yù)定義的巴克斯范式(Backus normal form,簡(jiǎn)稱BNF),從而發(fā)現(xiàn)語法錯(cuò)誤.程序語言的巴克斯范式一般屬于上下文無關(guān)文法,程序語法分析技術(shù)則主要包括算符優(yōu)先分析(自底向上)、遞歸下降分析(自頂向下)和LR分析(自左至右、自底向上)等,含有語法錯(cuò)誤的程序無法解析為語法樹.程序靜態(tài)分析還可以進(jìn)一步分析所生成的語法樹,以完成程序理解的其他相關(guān)任務(wù).例如在程序克隆檢測(cè)中,通過對(duì)比程序的語法樹之間的相似性來檢測(cè)程序克隆[26].

程序靜態(tài)分析與自然語言語法分析相似,但程序具有更強(qiáng)的結(jié)構(gòu)性且存在大量的嵌套結(jié)構(gòu),程序語法樹比自然語言語法樹要復(fù)雜得多,分析難度也更大.而且自然語言即使存在語法錯(cuò)誤,人仍可以根據(jù)其上下文來理解它的含義,但程序需要可執(zhí)行才能體現(xiàn)其價(jià)值,含有語法錯(cuò)誤的程序不能被正確執(zhí)行,因此程序分析中語法約束更加嚴(yán)格.

軟件系統(tǒng)用于求解特定領(lǐng)域問題,軟件系統(tǒng)的語義本質(zhì)上就是問題的求解過程.比如,軟件系統(tǒng)的控制流從操作的角度表達(dá)問題求解過程,它包括過程的細(xì)分,表達(dá)操作的順序步驟以及包含if-then-else條件、循環(huán)和/或分支路徑等操作的控制轉(zhuǎn)移.軟件系統(tǒng)的數(shù)據(jù)流從數(shù)據(jù)傳遞和加工角度表達(dá)了系統(tǒng)的邏輯功能,即數(shù)據(jù)在系統(tǒng)內(nèi)部的邏輯流向和邏輯變換過程.通過各種程序分析的手段抽象出系統(tǒng)的控制流和/或數(shù)據(jù)流的過程,可以看作是從問題求解過程視角出發(fā)的程序語義理解.

更深一個(gè)層次是程序的形式語義,它描述程序執(zhí)行時(shí)所遵循的規(guī)約,是關(guān)于程序執(zhí)行性質(zhì)的抽象.比如通過描述程序(程序語句)的輸入輸出關(guān)系,或者解釋程序的執(zhí)行步驟來創(chuàng)建其計(jì)算模型.關(guān)于這類語義的刻畫依賴于編程語言的形式語義.編程語言形式語義有 3種:一是操作語義,它通過規(guī)約程序在抽象機(jī)上的執(zhí)行過程來描述語言的語義;二是指稱語義,它認(rèn)為程序(或者程序成分)的語義是執(zhí)行該程序(或成分)所得到的最終效果,這個(gè)最終結(jié)果才是程序成分所要表達(dá)的含義,它通過構(gòu)造可描述語句含義的數(shù)學(xué)概念(稱為指稱)來表達(dá)語言的語義;三是公理語義,它使用公理化方法,通過描述程序語句在程序狀態(tài)斷言上的效果來定義程序語句的語義.

形式語義精確地表達(dá)了程序的執(zhí)行過程或執(zhí)行效果,但構(gòu)造形式語義相當(dāng)困難,目前只有一些非常有限的輔助手段.比如:符號(hào)執(zhí)行使用抽象符號(hào)來表達(dá)程序變量的值,用一個(gè)解釋器來跟蹤程序,從而確定哪些輸入會(huì)引起程序各個(gè)部分的執(zhí)行[27];然后,根據(jù)程序中表達(dá)式和變量的符號(hào)來獲得表達(dá)式,根據(jù)每個(gè)條件分支的可能結(jié)果獲得這些符號(hào)的約束.由于需要窮舉各種可能執(zhí)行的路徑,其搜索空間將隨程序規(guī)模的擴(kuò)大呈指數(shù)級(jí)增長(zhǎng).

2.2.2 基于動(dòng)態(tài)分析的程序理解

程序動(dòng)態(tài)分析用于分析程序運(yùn)行時(shí)性質(zhì),分析時(shí)需要采集程序運(yùn)行時(shí)信息,通過分析這些運(yùn)行時(shí)信息來獲得程序運(yùn)行時(shí)屬性.程序動(dòng)態(tài)分析的原因包括:一方面,動(dòng)態(tài)鏈接庫(kù)被廣泛使用,軟件只有在完成部署之后才能完整地表達(dá)程序的功能,這種情況下,傳統(tǒng)的僅依賴源碼分析的靜態(tài)分析獲得的結(jié)果由于可能缺少涉及動(dòng)態(tài)鏈接庫(kù)的信息而不夠精確[28];另一方面,面向?qū)ο笳Z言(尤其是 Java)被廣泛使用,這類語言具有動(dòng)態(tài)綁定、多態(tài)、線程等特征,這些特性也使靜態(tài)分析的結(jié)果受到限制.

基于插裝的方法,將監(jiān)測(cè)代碼插裝到程序中,以捕獲程序執(zhí)行路徑等相關(guān)信息[29].監(jiān)測(cè)代碼可以插裝在源代碼、二進(jìn)制碼以及字節(jié)碼中.源代碼插裝在程序編譯前進(jìn)行,它在需要監(jiān)測(cè)的地方直接加上監(jiān)測(cè)代碼,例如增加輸出信息語句、增加日志語句等.二進(jìn)制碼插裝需要修改或重寫編譯代碼來添加監(jiān)測(cè)代碼,分靜態(tài)插裝和動(dòng)態(tài)插裝:靜態(tài)二進(jìn)制碼插裝直接編寫可執(zhí)行二進(jìn)制碼重寫應(yīng)用程序;動(dòng)態(tài)二進(jìn)制插裝在程序加載到內(nèi)存后,在執(zhí)行之前進(jìn)行.字節(jié)碼插裝在已編譯的代碼中進(jìn)行追蹤,同樣也可分為靜態(tài)的或者動(dòng)態(tài)的:靜態(tài)字節(jié)碼插裝在程序執(zhí)行之前離線更改已編譯代碼,創(chuàng)建已插裝的中間代碼的副本;動(dòng)態(tài)字節(jié)碼插裝則在程序運(yùn)行時(shí)進(jìn)行.

基于虛擬機(jī)分析的方法通過使用特定虛擬機(jī)提供的分析(profiling)和調(diào)試(debugging)機(jī)制來執(zhí)行動(dòng)態(tài)分析[30],以深入了解程序的內(nèi)部操作,特別是與內(nèi)存和使用堆的相關(guān)操作.

從某種意義上說,基于動(dòng)態(tài)分析的程序理解可以類比于自然語言理解中的一種語用性理解,亦即在實(shí)際的程序運(yùn)行過程中捕捉程序的含義,建立程序的執(zhí)行及輸入輸出之間的依賴關(guān)系.

2.2.3 基于學(xué)習(xí)的程序理解

隨著大量開源代碼的出現(xiàn),程序相關(guān)數(shù)據(jù)越來越容易獲得.同時(shí),軟件是知識(shí)的載體,軟件開發(fā)是人類表達(dá)知識(shí)的行為,對(duì)大量代碼進(jìn)行統(tǒng)計(jì)建模來理解程序獲取知識(shí)具有合理性.因此,許多研究開始采用機(jī)器學(xué)習(xí)技術(shù),學(xué)習(xí)代碼數(shù)據(jù)和代碼文檔數(shù)據(jù)等其中蘊(yùn)含的知識(shí)[31].這些研究通過運(yùn)用統(tǒng)計(jì)學(xué)習(xí)和機(jī)器學(xué)習(xí)相關(guān)技術(shù)來挖掘程序的特征,進(jìn)行程序理解.

統(tǒng)計(jì)語言模型用于學(xué)習(xí)代碼中的統(tǒng)計(jì)特性.N-gram[32]是使用最為廣泛的模型,它基于的假設(shè)是:第N個(gè)詞的出現(xiàn)只與前N-1個(gè)詞相關(guān),因此可以用前N-1個(gè)連續(xù)的詞來預(yù)測(cè)下一個(gè)詞出現(xiàn)的概率.Hindle等人首先采用N-gram為程序語言建模[32],并用于代碼補(bǔ)全任務(wù).Nguyen等人對(duì)N-gram模型進(jìn)行了擴(kuò)展[33],在構(gòu)建模型時(shí)考慮了代碼中的語義信息.Tu等人觀察到代碼具有局部性特征[34],因此在N-gram模型的基礎(chǔ)上增加了緩存機(jī)制來記錄代碼的局部特性.但這些都屬于語句一級(jí)的理解,僅能用于進(jìn)行特定的編碼和程序分析.

一些經(jīng)典機(jī)器學(xué)習(xí)算法,如決策樹、條件隨機(jī)場(chǎng)等,被用于進(jìn)行程序理解.其中,條件隨機(jī)場(chǎng)(conditional random field,簡(jiǎn)稱 CRF)是一類判別式無向概率圖模型[35],用于編碼觀察間的已知關(guān)系并構(gòu)建與其一致的解釋.在程序理解中,該模型可以對(duì)多個(gè)變量在給定觀測(cè)值后的條件概率進(jìn)行建模,構(gòu)建代碼結(jié)構(gòu)以及代碼中元素間的依賴關(guān)系.比如,文獻(xiàn)[36]利用條件隨機(jī)場(chǎng)進(jìn)行程序元素的屬性預(yù)測(cè),包括預(yù)測(cè)變量名或變量類型.它首先將程序表示為一個(gè)依賴網(wǎng)絡(luò)(dependency network),以表達(dá)程序中各元素間的關(guān)系;然后構(gòu)建條件隨機(jī)場(chǎng)模型,從而對(duì)程序中元素屬性進(jìn)行預(yù)測(cè).其優(yōu)點(diǎn)是在預(yù)測(cè)過程中能夠充分考慮程序中各元素間的依賴關(guān)系和程序的結(jié)構(gòu),可提高預(yù)測(cè)的準(zhǔn)確率.決策樹是基于樹結(jié)構(gòu)進(jìn)行決策的方法,文獻(xiàn)[37]將學(xué)習(xí)代碼概率模型的問題看作是基于抽象語法樹學(xué)習(xí)領(lǐng)域特定語言上的決策樹的問題,從而支持在動(dòng)態(tài)計(jì)算上下文中調(diào)節(jié)程序元素的預(yù)測(cè).這些工作支持了程序中跨語句依賴關(guān)系的理解.

近年來,人們開始探索深度學(xué)習(xí)在程序理解上的應(yīng)用.以往的程序理解研究需要對(duì)程序數(shù)據(jù)進(jìn)行分析,獲取程序中包含的特征信息,然后根據(jù)這些先驗(yàn)知識(shí)人為地制定啟發(fā)式規(guī)則,這一過程非常耗時(shí)耗力.深度學(xué)習(xí)是一種數(shù)據(jù)驅(qū)動(dòng)的端到端的方法,將深度學(xué)習(xí)用于程序理解,目的是希望根據(jù)已有程序及其相關(guān)數(shù)據(jù),自動(dòng)地學(xué)習(xí)程序數(shù)據(jù)中蘊(yùn)含的特征,取代繁瑣的人工特征提取過程.目前,基于深度學(xué)習(xí)的程序分析大多是靜態(tài)的,即直接對(duì)程序源代碼或者其他抽象表示(如抽象語法樹、數(shù)據(jù)流圖等)進(jìn)行學(xué)習(xí).根據(jù)不同表示方式,可以分為如下幾個(gè)方面.

· 基于詞素(token)序列的理解:基于詞素序列的理解將程序表示為詞素序列,用深度神經(jīng)網(wǎng)絡(luò)對(duì)詞素序列進(jìn)行建模,學(xué)習(xí)詞素序列中包含的信息.這樣,當(dāng)給定部分詞素序列時(shí),模型可以預(yù)測(cè)下一個(gè)最有可能出現(xiàn)的詞素.這樣的模型可用于代碼補(bǔ)全任務(wù)中[38,39].這個(gè)學(xué)習(xí)過程也可以獲得整個(gè)程序詞素序列的特征向量表示,因此也可以完成程序注釋生成[40]、代碼檢索[41]等任務(wù);

· 基于應(yīng)用程序接口(API)序列的理解:基于 API序列的程序理解認(rèn)為程序中用到的API序列可以在一定程度上反映程序的功能特性,它將程序中包含的 API序列作為對(duì)象進(jìn)行建模,或者將 API序列作為額外信息輸入學(xué)習(xí)網(wǎng)絡(luò).這類模型可用于如代碼注釋生成[42]、代碼檢索[41]等任務(wù);

· 基于抽象語法樹(AST)的理解:抽象語法樹表示了程序的語法結(jié)構(gòu).利用深度神經(jīng)網(wǎng)絡(luò)對(duì)程序語法樹進(jìn)行建模,可學(xué)習(xí)到特定程序代碼數(shù)據(jù)集的語法和結(jié)構(gòu)信息.這類模型可用于包括代碼補(bǔ)全[43]、程序自動(dòng)生成[44,45]、代碼克隆檢測(cè)[46]等任務(wù)中;

· 基于圖的理解:程序還可以用基于圖的結(jié)構(gòu)來表示,例如控制流圖和數(shù)據(jù)依賴圖.把程序的圖表示作為學(xué)習(xí)模型的輸入,使得模型能更好地捕捉程序中變量間或活動(dòng)間的依賴關(guān)系.這類模型可用于包括程序驗(yàn)證[47]、程序變量名預(yù)測(cè)、誤用檢測(cè)[48]等任務(wù)中;

· 基于程序執(zhí)行動(dòng)態(tài)軌跡的理解:對(duì)程序的動(dòng)態(tài)執(zhí)行過程中產(chǎn)生的數(shù)據(jù)進(jìn)行程序建模,可以捕獲程序運(yùn)行時(shí)的性質(zhì),比如程序執(zhí)行軌跡(execution trace).這些執(zhí)行過程數(shù)據(jù)可以包含程序執(zhí)行時(shí)產(chǎn)生的中間結(jié)果,如執(zhí)行過程中調(diào)用的子程序及其參數(shù),或程序各變量值的變化.這類研究工作目前主要集中在程序綜合上[49-51].此外,文獻(xiàn)[52]還提出了基于程序執(zhí)行軌跡構(gòu)建程序表示模型,獲得程序的特征向量表示,并將此特征向量表示用于對(duì)程序錯(cuò)誤進(jìn)行分類.

2.3 程序理解與軟件工程任務(wù)

程序理解與軟件工程中的很多任務(wù)相關(guān),本小節(jié)選擇幾個(gè)典型的任務(wù),討論程序理解與它們之間的關(guān)系以及程序理解對(duì)解決這些問題的支撐作用.

2.3.1 程序理解與軟件維護(hù)

軟件維護(hù)是指根據(jù)需求變化或硬件環(huán)境變化對(duì)應(yīng)用程序的部分或全部進(jìn)行修改.實(shí)踐表明,50%~80%的軟件預(yù)算消耗在對(duì)現(xiàn)有系統(tǒng)的維護(hù)上[53].軟件維護(hù)包括如下幾個(gè)活動(dòng):與修改請(qǐng)求相關(guān)的軟件理解、修改影響分析和修改實(shí)施(包括重構(gòu)以及修改傳播分析)以及修改后系統(tǒng)調(diào)試與測(cè)試[54,55].其中,程序理解主要是分析并確定已有系統(tǒng)成分間的關(guān)聯(lián)關(guān)系、分析維護(hù)需求與目標(biāo)代碼間的映射關(guān)系等,還可以輔助維護(hù)人員理解已有系統(tǒng)代碼.比如,Snelting等人采用程序理解技術(shù)進(jìn)行類與接口層次的識(shí)別,以輔助維護(hù)人員理解軟件系統(tǒng)的結(jié)構(gòu)[56].一些程序理解工具,如程序切分器、靜態(tài)分析器、動(dòng)態(tài)分析器[57]等,可提示程序員選擇最值得關(guān)注的程序片段,顯示數(shù)據(jù)鏈和相關(guān)特征,使程序員能夠準(zhǔn)確跟蹤更改影響.靜態(tài)分析器還能幫助程序員快速提取模塊、過程、變量、數(shù)據(jù)元素、對(duì)象與類、類層次結(jié)構(gòu)等信息.這些工具可以用清晰可讀、可理解的方式組織源代碼,從而把程序員從煩躁的代碼閱讀中解放出來.

程序理解技術(shù)不僅能夠提取軟件元素間的依賴關(guān)系,還能支持軟件演化性分析.比如,文獻(xiàn)[58]從代碼演化過程中,提取開發(fā)過程和演化過程中的模式,從而提高源程序的可理解性;文獻(xiàn)[59]利用基于概念格的程序理解技術(shù),提取出協(xié)同修改模式,為軟件演化所需的維護(hù)活動(dòng)提供有效的度量.

2.3.2 程序理解與軟件測(cè)試

軟件測(cè)試是指在特定條件下對(duì)程序進(jìn)行操作,以發(fā)現(xiàn)程序錯(cuò)誤,衡量軟件質(zhì)量,并評(píng)估其是否滿足設(shè)計(jì)要求,目的在于檢驗(yàn)程序是否滿足需求,或弄清預(yù)期結(jié)果與實(shí)際結(jié)果間的距離.軟件測(cè)試既耗時(shí)又耗力,測(cè)試成本通常超過軟件首次發(fā)布后總成本的50%[60].

無論采用什么測(cè)試方法,測(cè)試員都需要了解測(cè)試對(duì)象的功能.軟件設(shè)計(jì)和實(shí)現(xiàn)文檔提供理解軟件的基本功能說明,但沒有提供代碼級(jí)別的測(cè)試信息,測(cè)試員只有閱讀源代碼才能知道函數(shù)級(jí)或語句級(jí)的功能,因此能全面反映程序功能的程序理解技術(shù),可以極大地提升軟件測(cè)試的效率和效果.

程序理解技術(shù)目前已經(jīng)用于軟件智能調(diào)試、軟件自動(dòng)測(cè)試和軟件安全漏洞發(fā)掘等任務(wù).如,IEEE軟件測(cè)試標(biāo)準(zhǔn)要求對(duì)能獨(dú)立測(cè)試的軟件成分進(jìn)行辨識(shí)[61],Cellier等人提出融合關(guān)聯(lián)規(guī)則與基于形式概念分析的程序理解技術(shù),幫助進(jìn)行錯(cuò)誤定位[62].通過概念格,很容易獲得錯(cuò)誤的測(cè)試和正確的測(cè)試間的特征差異,從而實(shí)現(xiàn)錯(cuò)誤定位.Ammons等人將類似的方法應(yīng)用于調(diào)試時(shí)態(tài)規(guī)約[63],大大提高了效率,只需檢查原有軌跡數(shù)量的 1/3,就可分類檢查出錯(cuò)誤與正確的規(guī)約.

符號(hào)執(zhí)行和抽象解釋等新方法,可以從外部和內(nèi)部自動(dòng)識(shí)別程序的運(yùn)行時(shí)特征.與此相關(guān)的其他技術(shù),如基于序列[64]和統(tǒng)計(jì)的軟件驗(yàn)證技術(shù)、模型驗(yàn)證技術(shù)、可攜帶證明代碼等,都成為當(dāng)前研究的熱點(diǎn).

2.3.3 程序理解與軟件重構(gòu)

軟件重構(gòu)是指:為了改善軟件的結(jié)構(gòu),提高軟件的清晰性、可擴(kuò)展性和可重用性,在不改變軟件功能和外部可見性的情況下,對(duì)其進(jìn)行的改造,使程序的設(shè)計(jì)模式和架構(gòu)更趨合理,從而提高軟件的可擴(kuò)展性和可維護(hù)性[65].主要研究包括類層次結(jié)構(gòu)重構(gòu)、模塊結(jié)構(gòu)、“壞味道”檢測(cè)和代碼重構(gòu),由低層次語言規(guī)范向高層次的語言規(guī)范進(jìn)行重構(gòu)等.

程序理解在不同層次的軟件重構(gòu)中都能發(fā)揮作用.如,Arévalo等人采用形式概念分析,將對(duì)象類結(jié)構(gòu)區(qū)分為好的層次設(shè)計(jì)、壞的層次設(shè)計(jì)和不正常的層次設(shè)計(jì),指導(dǎo)維護(hù)人員理解類層次以及修改類層次中存在的“壞味道”[66].Snelting等人提出了基于概念格進(jìn)行類層次重構(gòu)的方法[67],經(jīng)過重構(gòu)后的類層次更加合理.Bhatti 等人對(duì)過程式面向?qū)ο蟠a進(jìn)行分析,識(shí)別程序代碼中有用的類層次和結(jié)構(gòu),并進(jìn)行重構(gòu)[68].Al-Ekram等人將概念分類、程序切片及形式概念分析結(jié)合起來進(jìn)行重構(gòu)[69],使重構(gòu)后的模塊能夠自包含、模塊間有很小的沖突以及較少的代碼復(fù)制.Kim等人提出采用面向?qū)ο蟮母拍罘治龇椒ㄟM(jìn)行模塊重構(gòu)[70],該方法除保持了傳統(tǒng)形式概念分析方法的優(yōu)點(diǎn)外,還可直接粗粒度地識(shí)別模塊,適用于大規(guī)模軟件的模塊重構(gòu).

重構(gòu)過程中,對(duì)軟件進(jìn)行的修改會(huì)對(duì)軟件的其他部分造成潛在影響,可能導(dǎo)致軟件不一致.軟件修改影響分析可用于識(shí)別這些潛在影響[71].如,Tonella將概念分析與分解切片結(jié)合起來,提出一種基于分解切片概念格的程序理解方法[72],用于過程內(nèi)針對(duì)某語句或者變量修改的影響分析.

2.3.4 程序理解與軟件復(fù)用

軟件復(fù)用是指重復(fù)使用已有軟件的各種制品,包括各類文檔和代碼,來開發(fā)新的軟件,減少軟件開發(fā)和維護(hù)的開銷.程序理解技術(shù)支持軟件制品的理解,是軟件復(fù)用的關(guān)鍵技術(shù).

對(duì)可復(fù)用軟件制品的理解,特別是代碼功能的理解,是進(jìn)行復(fù)用的基礎(chǔ).如:Tonella等人通過程序理解從源代碼中提取設(shè)計(jì)模式[73],進(jìn)而指導(dǎo)程序的演化;Hill等人[74]通過分析與代碼相關(guān)的文檔、錯(cuò)誤報(bào)告等,猜測(cè)并標(biāo)注代碼功能;Vinz等人[75]分析代碼中的自然語言注釋,進(jìn)行軟件代碼的功能分析;Falleri等人[76]分析程序代碼中的變量名、方法名、類名等類自然語言標(biāo)識(shí)符,推測(cè)程序代碼的功能;Nguyen等人[77]通過建立程序語言的概率模型(如詞袋模型),進(jìn)而根據(jù)關(guān)鍵字或表達(dá)式的出現(xiàn)概率對(duì)代碼功能進(jìn)行推測(cè);Shepherd等人發(fā)現(xiàn)程序代碼的動(dòng)作可以用動(dòng)詞和名詞的組合來表示,因此提出一組規(guī)則和算法,根據(jù)程序代碼方法中的自定義標(biāo)識(shí)符生成簡(jiǎn)短的自然語言描述,作為對(duì)代碼功能的表達(dá)[78].

更細(xì)粒度的理解包括 Robillard等人在特征定位方面的工作[79,80],他們提出基于概念圖的方法,利用概念圖表示代碼不同成分間的關(guān)系,從而通過代碼中的成分進(jìn)行特征定位.

2.3.5 程序理解與需求追蹤

需求跟蹤是指跟蹤需求生命周期全過程,包括建立每個(gè)需求和系統(tǒng)元素之間的關(guān)聯(lián),比如和其他需求、體系結(jié)構(gòu)、系統(tǒng)構(gòu)件、源代碼模塊、測(cè)試案例之間的關(guān)聯(lián)等.程序理解在需求追蹤中的作用體現(xiàn)在特征定位方面,即,將自然語言形式的修改請(qǐng)求映射到代碼層的修改上,識(shí)別哪些代碼實(shí)現(xiàn)需求中的哪些功能(或者非功能)特性[81].如,Zhao等人提出了一種基于分支調(diào)用圖(branch reserving call graph)的程序理解方法[82],采用信息檢索技術(shù)建立關(guān)鍵詞與代碼功能單元之間的關(guān)系,利用分支調(diào)用圖表示不同功能單元間的關(guān)系;Chen等人基于特征定位技術(shù),提出一種基于抽象系統(tǒng)依賴圖(ASDG)的代碼表示方法[83],將函數(shù)或全局變量作為點(diǎn),它們之間的控制依賴關(guān)系作為邊,利用ASDG識(shí)別代碼的功能;Poshyvanyk等人引入形式概念分析,對(duì)代碼中不同對(duì)象的屬性進(jìn)行聚類分析,根據(jù)同類對(duì)象的共同屬性,建立層次概念模型,找出與指定特征最相關(guān)的類或方法,方便維護(hù)人員進(jìn)行特征定位[84].

程序理解技術(shù)在非代碼層次的需求分析方面的應(yīng)用包括:Ivkovic等人利用概念格聚集需求層次的各個(gè)模型元素,通過聚集得到的模型元素集合被認(rèn)為存在依賴關(guān)系[85];Niu等人通過形式概念分析來識(shí)別軟件演化產(chǎn)品線的模塊化和交互性需求,進(jìn)而檢查其功能和質(zhì)量需求[86].

2.3.6 程序理解與逆向工程

逆向工程是指分析目標(biāo)系統(tǒng),確定系統(tǒng)的成分及其相互關(guān)系,用高層抽象或其他形式來表達(dá)目標(biāo)系統(tǒng)[87].Muller等人將逆向工程,具體地說是信息系統(tǒng)逆向工程,細(xì)化為數(shù)據(jù)抽取、數(shù)據(jù)分析和概念抽象這3個(gè)階段[88]:數(shù)據(jù)抽取利用適當(dāng)?shù)某槿C(jī)制從目標(biāo)系統(tǒng)的執(zhí)行過程中收集原始數(shù)據(jù);數(shù)據(jù)分析從原始數(shù)據(jù)中發(fā)現(xiàn)結(jié)構(gòu)完整語義一致的邏輯數(shù)據(jù)模型;概念抽象則將數(shù)據(jù)分析中獲得的邏輯數(shù)據(jù)模型映射為等價(jià)的概念模型.

程序理解在逆向工程的數(shù)據(jù)抽取和數(shù)據(jù)分析活動(dòng)中都能發(fā)揮作用.例如:Harandi等人提出一種將代碼中與數(shù)據(jù)處理相關(guān)的部分組織為有層次結(jié)構(gòu)的事件模型[89],其中,底層為數(shù)據(jù)定義、聲明等,中間層為棧、隊(duì)列、樹等數(shù)據(jù)結(jié)構(gòu),高層為算法,然后將該事件模型與預(yù)定義的事件庫(kù)相比對(duì),找出可能與代碼功能相對(duì)應(yīng)的概念;Viljamaa等人基于程序理解技術(shù)從軟件框架中提取可重用性接口的規(guī)約和代碼[90];Marcus等人提出一種基于潛在語義索引(LSI)的方法[91],對(duì)代碼中的自定義標(biāo)識(shí)符進(jìn)行拆解,用拆解后的字段集合作為對(duì)代碼功能的表示,在此基礎(chǔ)上建立關(guān)于代碼文本描述的索引,以幫助在特征定位任務(wù)中確定代碼段的功能;Carey等人采用支持向量機(jī)對(duì)人工選擇的代碼特征進(jìn)行分類[92],將代碼劃分至不同的概念類別,建立代碼與表達(dá)功能的概念類別之間的關(guān)聯(lián);His等人提出一種基于圖匹配技術(shù)的代碼功能表示和識(shí)別方法[92],該方法首先建立代碼接口調(diào)用關(guān)系圖,然后通過接口調(diào)用圖的匹配定位實(shí)現(xiàn)指定功能的代碼段.

3 基于程序理解的延伸任務(wù)

近年來,深度學(xué)習(xí)方法的引入,使得程序理解逐步趨向于自動(dòng)化,也延伸了程序理解在軟件開發(fā)過程中的作用,基于理解的程序或軟件制品的自動(dòng)處理成為可能.本節(jié)介紹這個(gè)方面的一些最新進(jìn)展.

3.1 代碼補(bǔ)全

代碼補(bǔ)全是IDE,例如Eclipse、IntelliJ、Visual Studio等中使用頻率幾乎最高的功能[93],其本質(zhì)是基于關(guān)于代碼的普適知識(shí),預(yù)測(cè)當(dāng)前上下文中缺失的代碼.目前,大多數(shù)工作通過構(gòu)建語言模型來學(xué)習(xí)代碼 token的概率分布,根據(jù)已有部分代碼(context)來預(yù)測(cè)接下來最可能出現(xiàn)的token.前面曾經(jīng)提到,Hindle等人[32]使用了n-gram的語言模型,在token級(jí)別完成代碼補(bǔ)全.隨著深度學(xué)習(xí)的發(fā)展,深度神經(jīng)網(wǎng)絡(luò)模型,例如RNN、CNN等,都被應(yīng)用于代碼補(bǔ)全任務(wù)中,通過構(gòu)建深度神經(jīng)網(wǎng)絡(luò)模型,學(xué)習(xí)已有代碼的特征,基于這些特征完成代碼補(bǔ)全任務(wù),包括token級(jí)別、AST級(jí)別以及各類圖級(jí)別的補(bǔ)全.

3.2 代碼注釋生成

自動(dòng)生成給定代碼片段的自然語言描述,是程序理解的一個(gè)重要應(yīng)用場(chǎng)景.早期關(guān)于代碼注釋生成的研究,一般用啟發(fā)式規(guī)則提取代碼關(guān)鍵信息,再合成自然語言描述[94,95].深度學(xué)習(xí)的機(jī)制,比如基于 seq2seq框架的模型,可以大大提高代碼注釋生成的能力.比如,Iyer等人[40]采用了seq2seq模型,并引入了注意力機(jī)制,完成根據(jù)代碼片段生成自然語言描述的任務(wù).Hu等人[42]在基于seq2seq的程序注釋模型的基礎(chǔ)上,進(jìn)一步集成了代碼所調(diào)用的API序列,將API調(diào)用序列蘊(yùn)含的知識(shí)輸入到網(wǎng)絡(luò)模型中,以輔助注釋的生成,使模型生成的注釋能夠更好地描述代碼的功能.

3.3 代碼模式檢測(cè)、克隆檢測(cè)和缺陷檢測(cè)

代碼模式檢測(cè)[96]常用于進(jìn)行錯(cuò)誤檢測(cè)或代碼克隆檢測(cè).Mou等人[96]首次提出了基于樹結(jié)構(gòu)的卷積神經(jīng)網(wǎng)絡(luò),對(duì)程序 AST進(jìn)行建模,學(xué)習(xí)程序代碼的結(jié)構(gòu)信息,用于程序分類和代碼模式檢測(cè)任務(wù).White等人[97]和 Wei等人[46]通過深度神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)代碼中隱含的特征,根據(jù)得到的特征向量表示來判斷兩個(gè)代碼是否屬于一對(duì)克隆對(duì),改進(jìn)了克隆檢測(cè)的效果.

利用語言模型對(duì)代碼建模,就是對(duì)代碼段賦予其概率值.頻繁出現(xiàn)的代碼段獲得較高的概率值,而出現(xiàn)概率很低的代碼段則被認(rèn)為不太可能出現(xiàn),很可能是錯(cuò)誤代碼.一些研究基于這個(gè)假設(shè)構(gòu)建語言模型,進(jìn)行代碼缺陷檢測(cè).Wang等人[98]使用深度信念網(wǎng)絡(luò)學(xué)習(xí)token級(jí)別的代碼特征,用于預(yù)測(cè)代碼中的缺陷.Murali等人[99]結(jié)合了主題模型和循環(huán)神經(jīng)網(wǎng)絡(luò),對(duì)代碼中調(diào)用的API序列進(jìn)行建模,檢測(cè)代碼中是否包含不常用的API序列,以判斷代碼中是否包含錯(cuò)誤.

3.4 代碼風(fēng)格修正

除了程序語言自身的語法約束之外,代碼風(fēng)格也是約束程序的一種方式.例如命名風(fēng)格等,風(fēng)格規(guī)范的代碼有利于代碼的理解[100].對(duì)代碼風(fēng)格的研究主要包括變量名、函數(shù)名和類名的預(yù)測(cè)(重命名)以及代碼格式修正等.這些工作一般利用深度神經(jīng)網(wǎng)絡(luò)得到代碼的特征向量表示,然后根據(jù)這些向量表示完成風(fēng)格修正任務(wù).Allamanis等人[101]針對(duì)程序中的關(guān)鍵語句以及層次結(jié)構(gòu)性等特性,構(gòu)建基于注意力機(jī)制的卷積神經(jīng)網(wǎng)絡(luò),學(xué)習(xí)程序的這一特性,并用于程序函數(shù)名的預(yù)測(cè).Allamanis等人[48]采用圖結(jié)構(gòu)來表示程序,對(duì)程序中的數(shù)據(jù)依賴關(guān)系進(jìn)行建模,用于程序變量命名和變量誤用錯(cuò)誤檢測(cè)中.

4 趨勢(shì)與展望

軟件系統(tǒng)已經(jīng)成為信息社會(huì)的基礎(chǔ)設(shè)施,它面臨其軟硬件環(huán)境及外部資源不斷變化的挑戰(zhàn).增強(qiáng)軟件系統(tǒng)的自適應(yīng)和持續(xù)演化能力,使其能夠長(zhǎng)期生存并不斷成長(zhǎng),是當(dāng)前學(xué)術(shù)界研究的新熱點(diǎn).前面的技術(shù)分析顯示,軟件理解技術(shù)將在軟件系統(tǒng)自適應(yīng)和持續(xù)演化中扮演重要的角色,是支撐軟件系統(tǒng)能夠長(zhǎng)期生存和不斷成長(zhǎng)的不可或缺的基礎(chǔ)技術(shù).

同時(shí),在開放網(wǎng)絡(luò)環(huán)境下,“萬物互聯(lián)”的網(wǎng)絡(luò)空間推動(dòng)了人機(jī)物的深度融合,促進(jìn)應(yīng)用場(chǎng)景的普適化,軟件系統(tǒng)在規(guī)?;?、復(fù)雜度和異構(gòu)性上不斷提升,這給軟件系統(tǒng)理解帶來了新的需求和研究挑戰(zhàn),有必要重新認(rèn)識(shí)現(xiàn)有的程序理解技術(shù),提煉未來軟件系統(tǒng)理解的關(guān)鍵需求,從而確定進(jìn)一步的研究思路和可以突破的方向.我們同樣從技術(shù)的角度、工程的角度和認(rèn)知的角度,分析和討論程序理解的技術(shù)需求,目的是希望能把握未來研究選題的方向.

· 在理解的對(duì)象上:自然語言理解技術(shù)能夠理解的元素粒度從詞到句子再到段落再到篇章.相應(yīng)地,以從元素到合成物、從微觀向宏觀、從具體關(guān)聯(lián)到抽象關(guān)聯(lián)為維度建立譜系,程序理解應(yīng)該建立在軟件系統(tǒng)完整生命周期上的全譜系理解,包括從詞素和變量及其屬性值等的建模,到程序代碼語句結(jié)構(gòu)理解,再到程序調(diào)用關(guān)系建模和數(shù)據(jù)依賴關(guān)系建模,需要具備從程序片段的功能理解到程序系統(tǒng)的能力理解.總之,程序理解僅僅局限在源碼級(jí)的理解是遠(yuǎn)遠(yuǎn)不夠的,我們需要能夠理解:(1) 軟件系統(tǒng)構(gòu)件間的關(guān)系(架構(gòu)具有什么含義?);(2) 特定軟件系統(tǒng)中對(duì)應(yīng)現(xiàn)實(shí)世界問題表達(dá)的數(shù)據(jù)類型結(jié)構(gòu)(如何表達(dá)問題空間?);(3) 特定軟件系統(tǒng)問題求解過程調(diào)用關(guān)系的層次(如何求解現(xiàn)實(shí)問題?).更具挑戰(zhàn)性的是:在一定抽象層次上建立對(duì)大型軟件系統(tǒng)及其軟件體系結(jié)構(gòu)的某個(gè)方面(如良構(gòu)性、魯棒性、健康性等)的系統(tǒng)級(jí)量度及其度量方法,支持大型程序的系統(tǒng)級(jí)概述的獲得;

· 在理解的技術(shù)上:動(dòng)態(tài)分析技術(shù)將凸顯其重要性.動(dòng)態(tài)分析根據(jù)收集到的軟件系統(tǒng)運(yùn)行時(shí)數(shù)據(jù)進(jìn)行軟件系統(tǒng)的分析,它可以揭示軟件系統(tǒng)的真實(shí)行為,有可能建立軟件系統(tǒng)的準(zhǔn)確的表示.這個(gè)表示可以是語句層的調(diào)用關(guān)系、信息處理的變化過程,甚至體系結(jié)構(gòu)的視圖.隨著軟件系統(tǒng)規(guī)模的擴(kuò)大、復(fù)雜度的增長(zhǎng)以及軟件系統(tǒng)運(yùn)行上下文或運(yùn)行場(chǎng)景不確定性的提高,系統(tǒng)的動(dòng)態(tài)理解技術(shù)將越來越重要.同時(shí),在人機(jī)物互聯(lián)應(yīng)用環(huán)境下,動(dòng)態(tài)理解的范疇有可能不僅需要軟件系統(tǒng)本身的狀態(tài)感知,還需要結(jié)合互聯(lián)環(huán)境中的上下文感知和運(yùn)行場(chǎng)景感知.這種情況可以稱其為程序理解擴(kuò)大到系統(tǒng)理解;

· 在理解的層次上:從表達(dá)知識(shí)的角度看,程序理解具有與自然語言理解相似的特性,依據(jù)自然語言理解的層次,程序理解也可以遵循從語法分析到語義分析再到語用分析這樣一個(gè)由淺入深的過程.目前的技術(shù)大部分側(cè)重在程序語言語法分析上,部分技術(shù)涉及從信息處理視角出發(fā)的程序語義分析.但是從軟件系統(tǒng)逆向工程、軟件復(fù)用以及程序自適應(yīng)演化等的需求來看,程序或軟件系統(tǒng)的語用分析的重要性將逐步凸顯,這涉及對(duì)軟件系統(tǒng)的運(yùn)行時(shí)上下文、應(yīng)用場(chǎng)景或軟件系統(tǒng)作用環(huán)境的分析,從而決定軟件系統(tǒng)在當(dāng)前現(xiàn)實(shí)應(yīng)用場(chǎng)景中的適配性,決定在特定現(xiàn)實(shí)應(yīng)用場(chǎng)景下,軟件制品是否適合復(fù)用,或在應(yīng)用場(chǎng)景變化的情況下,軟件系統(tǒng)是否適合繼續(xù)使用(即是否需要調(diào)整和演化)等;

· 在理解的作用域上:從前面的分析中可以看到,程序理解的方法和理解結(jié)果可用于軟件工程的多個(gè)方面.目前有很多程序理解的工作,其目標(biāo)一方面是為了提高程序員理解程序的效率,提取一些具體的程序特征,輔助程序員去理解程序;另一方面是提取出程序中表達(dá)的知識(shí),支持逆向工程和知識(shí)復(fù)用.未來軟件系統(tǒng)越來越需要具有在線適應(yīng)、自主演化和自我成長(zhǎng)的能力,這要求對(duì)系統(tǒng)的理解過程要能完全自動(dòng)化,支持軟件系統(tǒng)的自我認(rèn)知或自我動(dòng)態(tài)認(rèn)知能力.關(guān)于這方面的一個(gè)值得關(guān)注的問題與運(yùn)行時(shí)模型相關(guān),軟件系統(tǒng)的自我認(rèn)知可以看作是它能掌握運(yùn)行時(shí)模型,并確保系統(tǒng)運(yùn)行狀態(tài)和運(yùn)行時(shí)模型的雙向同步.

5 結(jié)束語

程序理解是軟件工程中的一個(gè)重要活動(dòng),在完成軟件重用、維護(hù)、遷移、逆向工程以及軟件系統(tǒng)擴(kuò)展等任務(wù)時(shí),都要依賴于對(duì)程序的理解.在軟件工程的整個(gè)發(fā)展過程中,程序理解一直都占據(jù)著重要地位.隨著社會(huì)信息化進(jìn)程的不斷加快,程序理解研究的內(nèi)涵與需求等也發(fā)生了新的變化.因此,本文對(duì)程序理解進(jìn)行了重新審視.

本文首先給出了程序理解的定義,分別從學(xué)習(xí)和認(rèn)知角度、工程角度以及方法的角度對(duì)程序理解進(jìn)行了解釋.然后,通過文獻(xiàn)分析展示了長(zhǎng)期以來軟件工程領(lǐng)域中程序理解的研究布局.分析結(jié)果表明:程序理解一直都是軟件工程中的研究熱點(diǎn),并且隨著軟件工程的發(fā)展,程序理解的研究側(cè)重點(diǎn)也在隨之發(fā)生變化.然后,分別從認(rèn)知的角度、軟件工程的視角以及理解技術(shù)這 3個(gè)方面綜合論述程序理解研究的發(fā)展脈絡(luò)和研究進(jìn)展.最后,對(duì)程序理解的發(fā)展趨勢(shì)進(jìn)行了探討.

作為軟件工程領(lǐng)域研究的核心內(nèi)容之一,程序理解技術(shù)正在隨著互聯(lián)網(wǎng)各項(xiàng)技術(shù)的發(fā)展處于不斷推進(jìn)中,具有廣闊的研究前景和研究?jī)r(jià)值.隨著近幾年來人工智能和深度學(xué)習(xí)技術(shù)的發(fā)展,越來越多的學(xué)者開始研究如何運(yùn)用深度學(xué)習(xí)的方法實(shí)現(xiàn)程序分析的智能化與自動(dòng)化,程序理解的自動(dòng)化值得期待.

猜你喜歡
代碼語義程序
語言與語義
試論我國(guó)未決羈押程序的立法完善
創(chuàng)世代碼
創(chuàng)世代碼
創(chuàng)世代碼
創(chuàng)世代碼
“程序猿”的生活什么樣
英國(guó)與歐盟正式啟動(dòng)“離婚”程序程序
“上”與“下”語義的不對(duì)稱性及其認(rèn)知闡釋
創(chuàng)衛(wèi)暗訪程序有待改進(jìn)
东方市| 灵武市| 襄城县| 陈巴尔虎旗| 东丽区| 营口市| 饶阳县| 得荣县| 青神县| 万全县| 双牌县| 农安县| 石阡县| 类乌齐县| 东港市| 稻城县| 荃湾区| 南昌市| 德阳市| 玉龙| 罗城| 疏勒县| 侯马市| 兴国县| 宜春市| 建平县| 邯郸县| 本溪市| 定边县| 四会市| 廊坊市| 商水县| 当雄县| 湘潭县| 丰台区| 当涂县| 年辖:市辖区| 老河口市| 合山市| 靖西县| 绵阳市|