在 AI 編程工具引領(lǐng)潮流的當(dāng)下,許多開發(fā)者仍在觀望,疑惑這些“AI 輔助編碼”工具究竟有多大實用價值,是否值得為高昂的訂閱費用買單。本篇文章中,從事編程工作已有 36 年的開發(fā)者 Tom Yedwab 將以 Cursor 為例,分享他對這款工具的實際體驗與見解,希望能為仍在猶豫的讀者提供有價值的參考。
作者 | Tom Yedwab 責(zé)編 | 蘇宓出品 | CSDN(ID:CSDNnews)在 AI 編程的論壇中,我經(jīng)常會看到有軟件開發(fā)人員提出一個常見的問題:有人從 Cursor 這樣的工具中獲得價值嗎?為此付費訂閱是否值得?
于是,在將 Cursor 作為我個人和工作項目中日常工具使用了幾個月后,我有一些觀點想和大家分享,以此來討論這究竟是一個“必備”工具,還是僅僅曇花一現(xiàn)的流行產(chǎn)品。同時,我還會介紹一些快速獲得最大化收益的策略,希望能幫助那些想嘗試它的人?赡苡行┤嗽囘^ Cursor,覺得效果不盡人意,而這些建議也許能激勵你再給它一個機會。
我沒有受到 Cursor 的贊助,也不是產(chǎn)品評測者。我既不是要推崇它,也不是要貶低它,只是想分享我個人的使用體驗。
我是誰?
首先,先向大家介紹一下我自己。我是有一名有著 36 年編程經(jīng)驗的開發(fā)者,熟練掌握多種語言,主要專注于 C 語言為主的游戲引擎開發(fā),以及 Go、Python、JavaScript 的網(wǎng)頁開發(fā)。我假設(shè)這篇文章的讀者同樣能夠在大型代碼庫中自如地工作,能用自己擅長的語言編寫和調(diào)試代碼等。對于那些希望借助 AI 學(xué)習(xí)編程概念或想讓 AI 替他們寫超出自身水平的代碼的初學(xué)者,我會提供完全不同的建議!
對我來說,AI 助手的吸引力在于幫我處理模板化和重復(fù)性的工作,這樣我可以集中精力在每個問題的核心邏輯上。我對自動生成大量代碼并不特別感興趣,對“寫了多少行代碼”作為效率指標(biāo)持高度懷疑態(tài)度。我更希望在花費更少時間寫同樣多代碼的情況下,有更多時間去思考邊界情況、可維護性等問題。
那么,言歸正傳:
什么是 Cursor?
Cursor 是基于 Visual Studio Code(VS Code)開發(fā)的一個分支版本,內(nèi)置了大模型(LLM)支持的功能,集成在核心界面中。這是一個專有產(chǎn)品,開發(fā)商提供了免費和訂閱兩種方案;不過,價格表并沒有明確說明訂閱用戶的具體權(quán)益,以及與其他競品的區(qū)別。我會結(jié)合自己的理解,在后續(xù)功能介紹中盡量說明這一點,以下是簡要總結(jié):
Tab 補全:這是一組專有的微調(diào)模型,提供代碼補全功能,并可以通過 Tab 鍵跳轉(zhuǎn)到下一個推薦操作。該功能僅對訂閱用戶開放。
內(nèi)聯(lián)編輯(Inline editing):這是一個基于聊天界面的編輯工具,可以對選定代碼進行修改,并通過簡單的差異視圖顯示更改,采用基礎(chǔ)模型如 GPT 或 Claude。此功能對免費和付費用戶均開放。
聊天側(cè)邊欄:同樣是基于聊天的編輯界面,允許在側(cè)邊欄進行更大范圍的修改,支持更長的討論、多文件代碼建議等,采用基礎(chǔ)模型如 GPT 或 Claude。此功能對免費和付費用戶均開放。
Composer:這是專門用于跨代碼庫大規(guī)模重構(gòu)的聊天界面,生成多個文件的差異視圖供用戶逐一查看和批準,使用基礎(chǔ)模型如 GPT 或 Claude。此功能對免費和付費用戶均開放。
Tab 補全
雖然其他由 LLM 驅(qū)動的編碼工具更側(cè)重于聊天體驗,但在我使用 Cursor 的過程中,Tab 補全功能才是最符合我日常編碼習(xí)慣并能節(jié)省最多時間的功能。顯然,這個功能背后投入了大量的思考和技術(shù)研究,因此它不僅可以建議一行、多行,甚至整個函數(shù)的代碼補全,還可以建議下一個需要編輯的行。這樣一來,只需不斷按下 Tab 鍵,就能在整個文件中自動完成相關(guān)的修改。
使用它的一種用法是將它當(dāng)作一個“增強版”代碼重構(gòu)工具。例如,假設(shè)我有一段代碼塊,其中的變量名是 under_score,而我希望將它們改為 camelCase。我只需重命名一個變量的一個實例,然后逐行按 Tab 鍵,就能更新所有需要更改的行,包括其他相關(guān)變量。許多繁瑣、容易出錯的任務(wù)都可以通過這種方式自動完成,而無需額外編寫腳本:
有時 Tab 補全甚至?xí)毩l(fā)現(xiàn)并提出修復(fù) bug 的建議。很多時候,當(dāng)我在 Python 或 Go 中添加依賴項時,它會自動建議導(dǎo)入相應(yīng)的模塊。如果我將字符串用引號給括起來,它會適當(dāng)?shù)剞D(zhuǎn)義內(nèi)容。與其他工具類似,它還可以根據(jù)函數(shù)簽名和可選的文檔字符串生成整個函數(shù)代碼:
總體而言,這個工具感覺就像在讀我的心思,能預(yù)測我接下來的操作,讓我能更少關(guān)注代碼細節(jié),而更多專注于構(gòu)建的整體架構(gòu)。
值得一提的是,補全速度極快,幾乎是在我停止輸入的瞬間,代碼建議就彈出來了,完全沒有等待的感覺。如果這個過程拖延太久,那對我來說肯定會是個大缺點。
那么,我對 Tab 補全的抱怨是什么呢?第一個問題比較。河袝r候我沒及時看到補全建議就繼續(xù)輸入了,結(jié)果建議消失了。而一旦消失,似乎沒辦法讓它重新出現(xiàn),只有重新輸入一部分再試。
另一個問題剛好相反:有時補全的建議完全不合適,我會故意忽略它。然而,偶爾我選擇了一個不同的補全,但之前忽略的建議卻被悄悄應(yīng)用了。這種情況雖然不多,但已經(jīng)引發(fā)了一些難以察覺的 bug,因為我并未意識到不對的邏輯被誤用。這雖然不至于影響 Tab 補全帶來的效率提升,但確實稍微影響了體驗。
內(nèi)聯(lián)編輯、聊天側(cè)邊欄和 Composer
據(jù)我所知,這些功能在與基礎(chǔ)模型的交互上非常相似我?guī)缀踔挥?Claude 3.5 Sonnet主要區(qū)別在于用戶界面。
內(nèi)聯(lián)編輯可以通過選中代碼并按下 Ctrl-K/Cmd-K 啟動。我輸入想要的更改后,文件里會顯示一個清晰的差異視圖,讓我選擇接受或拒絕。我主要用它來添加小段代碼或做些小范圍的重構(gòu)。
一個典型的用法是,當(dāng)我有一個任務(wù)循環(huán)并想把它并行化時,就可以用這個功能來處理:
然后,你可以通過 Ctrl+L/Cmd+L 來打開聊天側(cè)邊欄,它為多輪對話提供了更大的操作空間。不過,我對當(dāng)前測試過的 LLM 模型有個小抱怨:它們總是先返回代碼,而不是在遇到歧義時先詢問澄清。建議的代碼會有一個“應(yīng)用”按鈕,點擊后可以在當(dāng)前選中的文件中生成差異視圖。這對于單文件的大規(guī)模重構(gòu),或基于當(dāng)前打開的文件創(chuàng)建新文件非常有用。如果涉及其他文件,它們可以手動添加到上下文中,不過 Cursor 會根據(jù)查詢和后臺生成的索引來猜測相關(guān)文件。
這里有一個示例:將應(yīng)用程序的數(shù)據(jù)庫 API 轉(zhuǎn)換為 REST API,并提供參數(shù)驗證和正確的 HTTP 狀態(tài)碼,然后再編寫一個客戶端庫來訪問這個 REST API:
另一個示例是將這個客戶端庫從 Python 轉(zhuǎn)換為 Go 語言,注意松散類型的 Python 代碼如何被轉(zhuǎn)換為結(jié)構(gòu)明確的結(jié)構(gòu)體類型,且符合 Go 慣用的錯誤處理風(fēng)格!這并非簡單的 1:1 重寫。
最后,Composer 專門用于跨文件的重構(gòu),這是我最少使用的功能,但它提供了一次性查看多個文件差異的良好體驗。
.cursorrules 文件
我最初并不知道這個功能的存在,直到在(我認為過于簡略的)文檔中偶然發(fā)現(xiàn)它,那時我看到各種聊天模式始終會包含位于工作區(qū)根目錄的 .cursorrules 文件的內(nèi)容,以提供額外的上下文。我目前在嘗試利用它來告知 LLM 有關(guān)代碼庫的編碼規(guī)范、常用包和其他文檔信息。
這個功能可能有助于解決我在使用 Cursor 時遇到的一個大難題:它無法遵循代碼風(fēng)格和模式,除非這些風(fēng)格已經(jīng)存在于你正在編輯的文件中。例如,在 Khan Academy,我們使用一個專有的 Go 庫來在函數(shù)間傳遞上下文,用于日志記錄、HTTP 請求等場景,所以 LLM 需要能夠使用這個庫。過去這一直很困難,但或許一個寫得好的 .cursorrules 文件可以作為改進的第一步。
目前的限制是每個工作區(qū)只能有一個 .cursorrules 文件,因此像我們這樣包含多種語言代碼的 monorepo 將比包含一個小型代碼庫(代碼風(fēng)格一致)要復(fù)雜得多且更難設(shè)置。
另外,文檔提到 .cursorrules 文件僅在聊天模式中使用,而不適用于 Tab 補全。不過,我嘗試將該文件固定在工作區(qū)的一個標(biāo)簽頁中,確認可以讓它至少部分參與到 Tab 補全的上下文中。
對我的工作流程的改變
像 Cursor 這樣的工具最令人興奮的地方并不是我可以更快地編寫代碼,畢竟寫代碼本身并不是瓶頸;事實上,我常常需要放慢速度,以免過分關(guān)注代碼本身而忽視要解決的高層次問題。真正的價值在于它改變了我的編碼方式。
雖然這種技術(shù)還處于早期階段,但到目前為止,我的工作方式已經(jīng)發(fā)生了以下變化,我也期待在不久的將來看到更多改變:
我現(xiàn)在在編碼時不太傾向于引入新的庫或框架。并不是說我自己會去寫加密庫,而是對于小型工具而言,直接讓 LLM 按我的需求生成定制代碼比引入一個通用庫更簡單。這些通用庫通常在剛推出時小巧且輕便,但因為是開放的并且被越來越多的人使用,所以它們慢慢會積累我不需要的功能和選項。
很多庫存在的意義只是為了減少樣板代碼,過去我會覺得這很值,因為有了這些庫可以幫我省下了寫和維護代碼的時間?涩F(xiàn)在,LLM 可以幫我完成這些重復(fù)性的工作,所以我覺得使用庫的成本就顯得有些不劃算了。而且,這個成本可能更高你試過讓一個寫了一年甚至更久的 Node.js 項目重新跑起來嗎?不過借助 LLM 干脆從頭再寫一遍。
我也不再擔(dān)心在自己的代碼中是否遵循 DRY(不要重復(fù)自己)。過早地定義抽象會導(dǎo)致后期的技術(shù)債增加,因此能夠參考其他代碼快速生成相似代碼,而不將其抽象為函數(shù)或類,為我提供了更大的靈活性。如果需要在未來將重復(fù)的邏輯重構(gòu)出來,LLM 也能提供幫助。
我對不熟悉的語言或框架的接受度也更高了。例如,多年來我一直在使用 R 語言,尤其是將它用于數(shù)據(jù)可視化。但說實話,我對它并不熟練,我對 dplyr 的理解不深,總覺得有很多不同的方法可以完成同樣的任務(wù)。現(xiàn)在我只需描述想要的可視化效果,LLM 就會自動生成相應(yīng)的數(shù)據(jù)操作和 ggplot 可視化。以前花一小時的任務(wù),現(xiàn)在五分鐘就能完成,所以我更不容易放棄轉(zhuǎn)而用 Python 來做了。
也許有一天我甚至?xí)?Rust 寫點什么;蛟S吧。
我現(xiàn)在會先對一些小模塊做快速調(diào)整,然后再把它們整合到大項目里面。這樣做的部分原因是因為 LLM 處理大項目有些吃力,另一方面也讓我發(fā)現(xiàn)了一些以前沒想到的工作方法。比如,我可以先用 Python 這種靈活的語言來做原型,解決好技術(shù)細節(jié)后,再迅速轉(zhuǎn)成類型嚴格的 Go 代碼,直接在 Web 應(yīng)用中。我還可以讓 LLM 自動生成測試數(shù)據(jù),或者模擬一個后端來對前端進行開發(fā)。既然一個想法還沒完全確定下來,為什么要一下子投入在成熟的大項目里付出高昂的成本呢?
總結(jié)
我不確定幾年后我是否還會繼續(xù)使用 Cursor,亦或者轉(zhuǎn)向其他工具。但可以肯定的是,在我撰寫本文時,我覺得 Cursor 是 LLM 編程助手的最佳工具。如果你想探索這類工具可能帶來的價值,我建議你試試 Cursor。