譯者 | 李睿
審校 | 重樓
對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),逐行仔細(xì)地檢查代碼并試圖掌握算法背后的復(fù)雜邏輯可能是一項(xiàng)繁重乏味的任務(wù),特別是在處理大型和復(fù)雜的代碼庫(kù)時(shí)。由于大型代碼庫(kù)使得識(shí)別所有潛在的測(cè)試場(chǎng)景變得困難重重,因此這種方法既耗時(shí)又令人不堪重負(fù)。幸運(yùn)的是,代碼圖形工具可以將這個(gè)過(guò)程實(shí)現(xiàn)自動(dòng)化,并通過(guò)圖形方式呈現(xiàn)代碼,從而簡(jiǎn)化了任務(wù)并提高整體效率。

本文將探討代碼圖的概念,它們?nèi)绾卧鰪?qiáng)代碼分析、簡(jiǎn)化調(diào)試和促進(jìn)影響分析,以及介紹一些能夠簡(jiǎn)化這些任務(wù)的工具。還將討論當(dāng)前代碼分析解決方案面臨的挑戰(zhàn),以及使用知識(shí)圖相對(duì)于向量數(shù)據(jù)庫(kù)在代碼分析方面的優(yōu)勢(shì)。
什么是代碼圖?
代碼圖直觀地表示代碼庫(kù)中的結(jié)構(gòu)關(guān)系。它將函數(shù)、類(lèi)和變量映射為節(jié)點(diǎn),并將它們之間的關(guān)系(例如函數(shù)調(diào)用、類(lèi)繼承和變量依賴(lài))映射為邊。這種結(jié)構(gòu)化表示通過(guò)使復(fù)雜的代碼庫(kù)更容易理解和導(dǎo)航來(lái)增強(qiáng)代碼分析。
代碼圖可以作為路線(xiàn)圖,清晰地展示代碼的不同部分如何組合在一起。為了幫助實(shí)現(xiàn)這一概念,一些工具能夠更輕松地實(shí)現(xiàn)可視化和導(dǎo)航代碼。例如,Visual Studio(2012-2017版)的可視化工具就使用代碼圖使用戶(hù)能夠更方便地探索代碼。
將代碼表示為圖形已在編譯器和集成開(kāi)發(fā)環(huán)境(IDE)中廣泛用于各種任務(wù)。將代碼的圖形結(jié)構(gòu)呈現(xiàn)給任何Graph ML算法都會(huì)創(chuàng)建SOTA結(jié)果。函數(shù)、類(lèi)和變量可以是代碼庫(kù)中的節(jié)點(diǎn)。邊可以表示函數(shù)調(diào)用、變量使用或類(lèi)繼承。例如,表示函數(shù)的節(jié)點(diǎn)可能有指向表示它所使用變量和它所調(diào)用函數(shù)的節(jié)點(diǎn)的邊。如圖1所示:
圖1 鏈接到兩個(gè)函數(shù)的代碼圖節(jié)點(diǎn)
代碼圖表示允許對(duì)代碼的結(jié)構(gòu)和行為進(jìn)行詳細(xì)的分析,從而便于完成代碼導(dǎo)航、影響分析和調(diào)試等任務(wù)。通過(guò)將代碼表示為圖形,捕獲了關(guān)于代碼的不同部分如何交互的復(fù)雜細(xì)節(jié),從而使分析和理解復(fù)雜的代碼庫(kù)變得更加容易。這是如何實(shí)現(xiàn)的?
將代碼分為以下元素:
- 定義:定義事物(如函數(shù)、類(lèi)、變量)的地方。
- 引用:這些事物被使用或調(diào)用的地方。
- 符號(hào):代碼中元素的名稱(chēng)(例如函數(shù)名和類(lèi)名)。
- 文檔注釋?zhuān)航忉尨a的注釋?zhuān)ǔR蕴囟ǜ袷骄帉?xiě)。
接下來(lái),將看到如何為給定代碼生成圖形的示例。
代碼圖如何增強(qiáng)代碼分析
代碼圖為代碼分析提供了幾個(gè)好處:
依賴(lài)關(guān)系可視化
使用代碼圖,開(kāi)發(fā)人員或測(cè)試人員可以可視化代碼不同部分之間的依賴(lài)關(guān)系。這樣就很容易看出函數(shù)、類(lèi)和模塊是如何相互依賴(lài)的。
想象一個(gè)大型的代碼庫(kù),其中有一個(gè)函數(shù)calculate_volume,還有一個(gè)calculate_area函數(shù),并依賴(lài)于輔助函數(shù)來(lái)獲取長(zhǎng)度和寬度。代碼圖將清楚地說(shuō)明這些依賴(lài)關(guān)系,允許開(kāi)發(fā)人員快速識(shí)別潛在的問(wèn)題或需要優(yōu)化的領(lǐng)域。
簡(jiǎn)化調(diào)試
代碼圖通過(guò)顯示函數(shù)和類(lèi)如何交互來(lái)簡(jiǎn)化調(diào)試。假設(shè)開(kāi)發(fā)人員正在調(diào)試calculate_volume函數(shù)的問(wèn)題。通過(guò)查看代碼圖,他們可以很快發(fā)現(xiàn)問(wèn)題可能是由calculate_area函數(shù)(稱(chēng)為calculate_volume)中的問(wèn)題引起的。然后,開(kāi)發(fā)人員可以將調(diào)試工作集中在calculate_area及其依賴(lài)項(xiàng)get_length和get_width上。
影響分析
開(kāi)發(fā)人員可以快速評(píng)估代碼一部分的更改對(duì)其他部分的影響。這是因?yàn)樗麄兛梢詸z查哪些函數(shù)或類(lèi)依賴(lài)于他們要修改的代碼。因此,他們可以做出明智的決定。
改進(jìn)代碼質(zhì)量
識(shí)別和理解代碼關(guān)系有助于維護(hù)和改進(jìn)代碼質(zhì)量,但是如何實(shí)現(xiàn)呢?現(xiàn)在,開(kāi)發(fā)人員可以找出代碼重復(fù)的地方,然后可以重構(gòu)代碼以改進(jìn)代碼庫(kù)。
代碼分析RAG解決方案面臨的挑戰(zhàn)
大型代碼庫(kù)
由于代碼量巨大,檢索增強(qiáng)生成(RAG)模型難以檢索相關(guān)的代碼片段。當(dāng)處理一個(gè)龐大的軟件系統(tǒng)時(shí),RAG模型會(huì)得到1000個(gè)代碼片段,為了選出最好的一個(gè),可能會(huì)閱讀數(shù)百個(gè)看起來(lái)相似的代碼片段。
代碼冗余
RAG模型可能產(chǎn)生冗余的代碼,導(dǎo)致代碼重復(fù),并可能降低效率。例如,在為某個(gè)任務(wù)生成不變代碼時(shí),RAG模型可能會(huì)提供多個(gè)看起來(lái)相似的解決方案,而比較它們并找出最佳方案似乎非常困難。
在代碼分析中使用知識(shí)圖優(yōu)于向量數(shù)據(jù)庫(kù)的優(yōu)勢(shì)
對(duì)于代碼分析,知識(shí)圖與向量數(shù)據(jù)庫(kù)相比具有幾個(gè)優(yōu)勢(shì)。可以通過(guò)一個(gè)例子來(lái)理解這一點(diǎn)。假設(shè)開(kāi)發(fā)人員給出了這個(gè)提示。
- 提示:搜索有關(guān)updateInventory()的代碼。
以下查看知識(shí)圖譜和向量數(shù)據(jù)庫(kù)將提供什么結(jié)果。
知識(shí)圖譜(Knowledge Graph)
查詢(xún)返回一個(gè)詳細(xì)的圖表,突出顯示直接或間接調(diào)用updateInventory()的每個(gè)方法、類(lèi)和服務(wù)。因此,在將結(jié)果提供給查詢(xún)之前,知識(shí)圖譜將檢查所有相關(guān)的函數(shù)、類(lèi)和服務(wù)以及它們與updateInventory()的關(guān)系,如下所示:
訂單服務(wù)(OrderService):調(diào)用updateInventory()來(lái)更新庫(kù)存水平。
- 退貨服務(wù)(ReturnService):該函數(shù)用于在處理退貨時(shí)重新補(bǔ)貨。
- 審計(jì)服務(wù)(AuditService):它記錄庫(kù)存更改以用于審計(jì)。
- 外部API(ExternalAPI):該函數(shù)與外部API交互以同步庫(kù)存數(shù)據(jù)。
- 性能指標(biāo)(PerformanceMetrics):該圖表包括性能數(shù)據(jù),顯示updateInventory()在高峰時(shí)段存在瓶頸。
這將確保返回的結(jié)果準(zhǔn)確可靠,因?yàn)榭紤]了與updateInventory()相關(guān)的所有組件及其與它的關(guān)系。這有助于代碼圖表示準(zhǔn)確的代碼可視化。
向量數(shù)據(jù)庫(kù)
向量數(shù)據(jù)庫(kù)對(duì)于查找相似的代碼片段很有用,但不能有效地表示詳細(xì)的場(chǎng)景關(guān)系。搜索返回的函數(shù)在結(jié)構(gòu)和內(nèi)容上都類(lèi)似于updateInventory。為什么? 向量數(shù)據(jù)庫(kù)可以基于相似性搜索或歐幾里德距離提供結(jié)果。
Plain Text
[FunctionX] --similar_to--> [updateInventory]
[FunctionY] --similar_to--> [updateInventory]
[FunctionZ] --similar_to--> [updateInventory]采用代碼圖可視化代碼
示例1
其中一個(gè)示例演示了Python中的基本函數(shù)定義和調(diào)用。它顯示了簡(jiǎn)單的算術(shù)運(yùn)算,例如乘法、加法和打印結(jié)果。
示例2
另一個(gè)示例演示了一個(gè)簡(jiǎn)單的遞歸函數(shù),用于計(jì)算數(shù)字的階乘,以及如何在主函數(shù)中調(diào)用它。
網(wǎng)上有許多代碼圖工具,您可以簡(jiǎn)單地粘貼整個(gè)代碼。另一種選擇是使用Lucidchart手工制作圖表。
理解代碼圖工作流
可以利用一個(gè)例子來(lái)理解它。假設(shè)一個(gè)Python項(xiàng)目有幾個(gè)文件,包括包含函數(shù)calculate_area()的math_utils.py和包含類(lèi)Circle的shapes.py。索引步驟將提取函數(shù)和類(lèi)定義及其關(guān)系,例如Circle使用calculate_area()。代碼圖的工作流程通常包括:
步驟1:索引
在這一步驟中,源代碼文件解析代碼庫(kù),提取相關(guān)信息,例如函數(shù)、類(lèi)、變量及其關(guān)系。
步驟2:構(gòu)建代碼圖
這一示例的代碼圖將包含calculate_area()和Circle的節(jié)點(diǎn),其中一條邊將Circle連接到calculate_area(),表明Circle使用calculate_area()函數(shù)。
步驟3:查詢(xún)代碼圖
用戶(hù)可以查詢(xún)代碼圖來(lái)查找Circle類(lèi)使用的所有函數(shù)。該查詢(xún)將通過(guò)檢查與函數(shù)連接的節(jié)點(diǎn)和實(shí)體返回一個(gè)函數(shù)列表。這可以使用圖形查詢(xún)語(yǔ)言(如Cypher或Gremlin)來(lái)完成。
步驟4:可視化和探索
可視化可能會(huì)顯示Circle的節(jié)點(diǎn),其邊指向calculate_area(),表示依賴(lài)關(guān)系。這種可視化幫助開(kāi)發(fā)人員快速識(shí)別代碼實(shí)體之間的關(guān)系。
步驟5:分析和洞察
通過(guò)分析代碼圖,可能會(huì)發(fā)現(xiàn)Circle類(lèi)與calculate_area()函數(shù)緊密耦合,這可能會(huì)導(dǎo)致維護(hù)問(wèn)題。還可以確定calculate_area()函數(shù)在代碼庫(kù)的另一部分重復(fù)。
與OpenAI交互轉(zhuǎn)換查詢(xún)
有時(shí),還可以使用OpenAI Codex模型與查詢(xún)轉(zhuǎn)換進(jìn)行交互,該模型可以針對(duì)多種代碼轉(zhuǎn)換任務(wù)進(jìn)行微調(diào),例如使用OpenAI代碼采樣重構(gòu)現(xiàn)有代碼,并使用SQL Codex Art轉(zhuǎn)換表。例如,給定CSV文件中的數(shù)據(jù)集,編寫(xiě)SQL查詢(xún)從數(shù)據(jù)集提取一些信息。
- 自動(dòng)補(bǔ)全:OpenAI的模型可以使用機(jī)器學(xué)習(xí)補(bǔ)全不完整的代碼,減少開(kāi)發(fā)人員的時(shí)間。
- 代碼轉(zhuǎn)換:模型可以將代碼從一種編程語(yǔ)言轉(zhuǎn)換為另一種編程語(yǔ)言,這使得在語(yǔ)言之間重新定位項(xiàng)目變得很簡(jiǎn)單。
- CodeOpt:OpenAI公司開(kāi)源了他們的代碼優(yōu)化模型,從而有助于提高代碼的性能。總的來(lái)說(shuō),這節(jié)省了大量的計(jì)算資源,以換取更高的效率。
- 代碼解釋:它幫助模型將晦澀的代碼片段轉(zhuǎn)換為更簡(jiǎn)單的單詞,這使得開(kāi)發(fā)人員更容易理解和相互學(xué)習(xí)代碼。
詳盡的知識(shí)圖譜模式
知識(shí)圖模式是對(duì)數(shù)據(jù)所在位置的本質(zhì)的理解。它定義了所有細(xì)節(jié)、實(shí)體之間的關(guān)系、屬性或概念,以及知識(shí)圖譜中呈現(xiàn)的所有內(nèi)容。它提供了一種組織和連接數(shù)據(jù)的標(biāo)準(zhǔn)化方法,允許機(jī)器解釋這些信息的意義和關(guān)系。
以下利用一個(gè)關(guān)于電影的假設(shè)知識(shí)圖來(lái)理解這一點(diǎn):
實(shí)體
(1)電影:表示一個(gè)電影實(shí)體。
- 屬性:片名(字符串)、上映日期(日期)、導(dǎo)演(人物)、類(lèi)型(字符串)、評(píng)分(浮動(dòng))、票房收入(浮動(dòng))、劇情簡(jiǎn)介(文本)
(2)人物:代表從事電影行業(yè)的人。
- 屬性:姓名(字符串),出生日期(日期),出生地點(diǎn)(字符串),傳記(文本),圖片(URL)
(3)類(lèi)型:代表一種電影類(lèi)型。
- 屬性:名稱(chēng)(字符串),描述(文本)
(4)工作室:代表電影制作工作室。
- 屬性:名稱(chēng)(字符串)、總部(字符串)、成立(日期)、描述(文本)、圖片(URL)
(5)獎(jiǎng)項(xiàng):表示授予電影的獎(jiǎng)項(xiàng)。
- 屬性:名稱(chēng)(字符串),類(lèi)別(字符串),年份(日期),收件人(人物或電影)
構(gòu)建代碼圖
首先,克隆FalkorDB代碼圖存儲(chǔ)庫(kù)。
Plain Text
git clone https://github.com/FalkorDB/code-graph.git運(yùn)行FalkorDB。
Plain Text
docker run -p 6379:6379 -it --rm falkordb/falkordb將OpenAI API密鑰設(shè)置為環(huán)境變量。將需要它為知識(shí)圖譜生成密碼查詢(xún),并回答與代碼圖相關(guān)的RAG問(wèn)題。
Plain Text
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY啟動(dòng)FalkorDB代碼圖工具。
Plain Text
npm run dev這將在http://localhost:3000/上啟動(dòng)一個(gè)服務(wù)器。可以輸入任何存儲(chǔ)庫(kù)的GitHub URL,它將生成代碼圖。
還可以在側(cè)邊欄中詢(xún)問(wèn)有關(guān)代碼圖的問(wèn)題,它將以自然語(yǔ)言回答。在瀏覽編程框架復(fù)雜而龐大的代碼庫(kù)時(shí),這個(gè)功能非常有用。
未來(lái)的改進(jìn)
代碼圖有很大的改進(jìn)空間,特別是在加強(qiáng)與各種開(kāi)發(fā)工具和平臺(tái)的集成方面。一個(gè)關(guān)鍵方面在于確保實(shí)時(shí)更新,使代碼圖與代碼庫(kù)中的變化保持同步。另一個(gè)重要的開(kāi)發(fā)領(lǐng)域是擴(kuò)大支持的編程語(yǔ)言范圍,使代碼圖更加通用,并適用于不同的開(kāi)發(fā)環(huán)境。此外,利用機(jī)器學(xué)習(xí)進(jìn)行預(yù)測(cè)分析和代碼推薦,在進(jìn)一步提高代碼圖的實(shí)用性和有效性方面具有巨大的潛力。
這些改進(jìn)可以幫助開(kāi)發(fā)人員更全面地了解他們的代碼庫(kù),使他們能夠進(jìn)行更徹底的代碼分析,并最終提高整體代碼質(zhì)量。
原文標(biāo)題:Enhancing Code Analysis With Code Graphs,作者:Balaji Dhamodharan























