
用 AI 改代碼這件事最常聽到的兩種說法是一種說“AI 能幫我把代碼寫得更優雅”另一種說“AI 生成的東西根本不能用”。我實際跑過一段時間之后結論更偏中間AI 確實能把代碼改好但前提是你得把它當成一個需要明確任務書的協作對象而不是一個丟一段代碼就能自動優化的黑盒工具。這篇文章不講概念講一套我自己一直在用的實操流程覆蓋代碼審查、局部重構、補測試、批量調整、報錯排查和 AI Agent 的邊界。適合正在用或準備用 AI 編程工具的開發者看尤其是那些已經過了“讓 AI 寫個爬蟲試試”的階段、想真正把 AI 嵌進日常開發流程里的人。最值得關注的一點是AI 改代碼是否靠譜大概率不取決于模型選得多新而取決于你在交給它任務之前有沒有把上下文、約束、驗證方式和驗收標準交代清楚。下面按我從環境準備到最終合入的真實順序拆開講。1. 先用一句話說清楚AI 改代碼到底改的是什么1.1 判斷代碼有沒有更好的三個維度先說“更好”的定義。不同場景里的“更好”完全不是一回事至少可以拆成三個維度。第一是可讀性。命名是否清楚函數是否過長邏輯是否繞注釋是否解釋了“為什么”。這類改動 AI 做得最穩因為它不需要理解業務只需要遵循編碼習慣。第二是正確性。有沒有漏掉邊界條件異常路徑是否被吞掉狀態更新是否遺漏并發場景下是否存在競態。這類改動 AI 能發現一部分但最終確認必須由人來做。尤其是業務規則相關的正確性AI 沒有真實業務背景經常會把“看起來合理”當成“實際正確”。第三是可維護性。重復代碼是否被提取模塊邊界是否合理依賴方向是否正確新功能能否低成本加進去。這一維度最難因為涉及項目歷史和團隊約定AI 在單次對話里基本看不到全貌。所以結論很簡單AI 最適合改第一類可以輔助第二類第三類要慎重。只要把任務落在這三個維度里AI 就不會變成“瞎優化”。1.2 AI 擅長什么不擅長什么我把實際用下來比較穩定的能力列一下。擅長的事單個文件內的局部重構比如把一個 300 行的函數拆成幾個小函數。補充單元測試尤其是純函數、工具類、數據轉換這類輸入輸出明確的代碼。解釋陌生代碼生成調用關系說明。遵循已有的 lint 規則修代碼風格問題。替換棄用 API 調用統一 import 路徑。定位明顯的空指針、未處理異常、變量作用域問題。不擅長的事跨多個模塊甚至跨服務的架構重構。需要業務判斷的刪改比如“這個字段是否還需要保留”。真實性能問題AI 只能憑經驗猜不能替代壓測。安全邊界判斷尤其是涉及權限、認證、敏感數據的代碼。保持“團隊歷史風格”的自覺性AI 很容易把局部代碼改得比全項目超前一個版本。這部分認知很重要。你會發現凡是 AI 擅長的都有一個共同點任務邊界清楚驗收標準明確。凡是不擅長的都需要大量項目上下文和人為經驗。因此工作流設計的目標就是盡量把任務變成前者。2. 開始之前先把環境和工具鏈準備好2.1 三類接入方式按場景選擇目前常見的接入方式大致有三類。不用糾結選哪個“最強”按任務類型選更合適。接入方式典型場景特點我常用的判斷IDE 內 AI 插件邊寫邊補全、代碼審查、快速解釋上下文自動帶出操作輕量適合日常小改動和學習命令行 AI 編程助手項目級重構、批量任務、按指令改動多個文件能讀整個項目結構執行鏈完整適合做單文件和批量改動比如 Claude Code、OpenCode 這類工具直接調用 API沉淀成團隊內部工具、CI 集成、自動化腳本可控性最強需要自己處理提示詞和上下文適合做成代碼審查機器人之類的固定流程我在日常開發里會用 IDE 插件做實時輔助用命令行 Agent 做稍大規模的改動。兩類工具不沖突甚至可以串起來用先用 Agent 做批量調整再用 IDE 插件逐段 review。2.2 項目條件比工具數量重要不管用哪類工具項目本身必須滿足幾個前置條件否則 AI 給的改動根本無法驗證。第一代碼必須在版本管理里隨時能回滾。這是最硬的條件。沒有 git 這類版本管理工具AI 的一次大改動就可能讓你丟失原有可用版本。我見過不止一次AI 重構之后功能測試掛了最后全靠git checkout恢復。第二構建和測試命令必須可復現。建議在項目根目錄寫清楚npm install npm run build npm testAI 工具在執行改動前通常會嘗試跑構建和測試。如果命令本身在你的機器上都跑不通那 AI 在改動后也無法判斷結果。所以要先保證一個干凈的基礎環境。第三AI 的改動放在單獨分支里。不要直接在開發主干上讓 AI 折騰。獨立分支的好處是diff 歷史清晰出問題不影響其他人合入前還能再做一次完整檢查git checkout -b ai-refactor/xxx第四輸入文件要穩定。編碼、換行符、生成文件路徑這些細節很容易被 AI 在重構時順手改掉造成大量沒有意義的大 diff。2.3 常見報錯先查 API Key 和環境變量AI 編程工具接入時報錯最多的不是模型本身問題而是認證和配置。我遇到過最典型的報錯類似unexpected status 401 unauthorized: {code:api_key_required,message:api key required}這個報錯基本不用懷疑代碼邏輯直接按順序檢查三件事。先看 API Key 是否真的配置了。很多工具通過環境變量讀取而不是直接寫在對話框里。確認環境變量名是否和工具文檔完全一致echo $ANTHROPIC_API_KEY echo $OPENAI_API_KEY再看 Key 權限范圍。有的 Key 只允許訪問部分模型或部分接口權限不足也會返回 401 或 403。可以在命令行里先發一個最小請求驗證 Key 是否有效而不是直接跑完整項目。最后看請求是否真的帶上了認證頭。有些代理配置、腳本封裝、自定義命令行工具會在轉發請求時把 Header 丟掉導致服務端識別不到身份。遇到 401 先查 Key 和環境變量不要急著換工具或重裝。能把日志完整讀一遍的人問題已經解決一半。3. 一套能落地的 AI 改代碼工作流3.1 先讓 AI 解釋代碼不急著讓它改拿到一段要改的代碼最忌諱的操作是上來就發一句“幫我優化這段代碼”。因為 AI 沒有和你共享思維它不知道這段代碼在業務里扮演什么角色也不知道哪些邊界必須保留。我的做法是先讓它用人類語言復述代碼邏輯。可以這樣問請先解釋這個函數做了什么。輸入是什么輸出是什么有哪些副作用函數被哪些地方調用這一步有三個作用。一是驗證 AI 是否真的理解代碼。如果它把核心邏輯說錯了那后續任何改動都不可信這時候應該換更小的上下文或者換提問方式。二是讓 AI 在回答過程中建立起對代碼的“心理模型”。后續讓它改代碼時它會更傾向于保留原始行為。三是你自己也能借這個過程重新整理一遍代碼邏輯。很多時候代碼寫久了你以為自己知道它干嘛真讓你講一遍反而講不清楚。3.2 單文件、小目標做可回滾的局部重構通過解釋驗證沒問題之后再進入修改階段。第一原則是單文件、小目標。比如一個文件里有兩個重復的函數目標是“抽取公共函數”。動作就只做這一件不要同時改命名、加注釋、換格式、調日志。每多一類改動review 成本就指數上升而且出了問題很難定位是哪一步引入的。具體步驟可以這樣選定一個文件先完整理解邏輯。告訴 AI 只改這個文件只解決一個明確問題。讓 AI 給出 diff而不是整個文件重寫。把 diff 應用到代碼跑構建和測試。確認通過之后再進入下一個文件或下一個問題。diff 比全量代碼好 review 得多。我看代碼合入時幾乎不看 AI 重寫的整個文件只看它實際改動了哪些行。3.3 補測試優先于改邏輯對有測試覆蓋的項目我強烈建議一個順序先讓 AI 基于當前行為補測試再根據測試結果決定是否修邏輯。原因是AI 直接改邏輯時很容易把一個“應該被修復的問題”和“當前系統依賴的行為”一起改掉。測試的作用就是先把當前行為凍結住。具體操作請為這個模塊補充單元測試。測試范圍正常輸入、邊界輸入、異常輸入。不要修改被測代碼。然后運行測試。如果測試全部通過說明當前代碼行為和你預期的行為一致那就不需要動邏輯最多做重構。如果有些測試跑紅了說明當前行為和你預期不一致。這時候讓 AI 看測試失敗信息再決定動哪個位置的代碼。這個流程可以把“AI 改壞了”的概率壓到很低因為你先定義了行為再允許它調整實現。3.4 批量任務要按“單一改動類型”拆分到了批量場景任務拆分比單文件重要得多。我見過一個團隊讓 AI 一次性做四件事統一命名風格、加類型標注、修所有 lint 警告、把 Promise 改成 async/await。最后 diff 大到沒法 review而且四個目標之間互相干擾。正確做法是每一輪只處理一類改動第一輪統一命名規范。第二輪補類型標注。第三輪修 lint 警告。第四輪換異步寫法。每一輪單獨提交單獨跑測試。這樣做的好處是如果你的測試覆蓋足夠某一輪出了問題可以直接回滾這一輪提交不影響其他已經完成的工作。批量任務還要特別注意輸出命名。AI 在處理多個文件時很容易生成臨時文件、備份文件或者把原有文件覆蓋到錯誤位置。批量跑之前一定要在獨立分支里操作并且設置明確的輸出目錄和命名規則。4. 提示詞怎么組織AI 才不瞎改4.1 有效提示詞的四個要素我把這些年摸索出來的提示詞套路總結成四個要素。上下文。告訴 AI 它正在處理什么項目、什么語言、什么框架代碼路徑是什么。不要只丟一個函數片段就讓它猜整個項目。約束。明確告訴 AI 哪些不能動。常見約束包括公共接口不能變、外部依賴不能換、不要引入新的設計模式、只修改指定文件。驗證方式。告訴 AI 改完代碼后可以用什么命令驗證結果的正確性。這會讓 AI 在改動時自動避開容易破壞測試的方案。輸出格式。要求 AI 按一定格式輸出比如先說明問題再給出 diff再解釋每處改動理由。這樣不容易把“無用改動”混在“必要改動”里。4.2 一個可直接改用的代碼審查提示詞示例下面是我比較常用的一個審查提示詞你可以根據項目情況改你是這個項目的資深開發者。請對一個函數做保守的代碼審查。 第一步解釋這個函數現在做了什么包括輸入、輸出和副作用。 第二步列出潛在問題按嚴重程度排序嚴重、一般、輕微。 第三步對每個問題給出最小改動建議。不要重寫整個函數不要改變對外行為不要引入新的抽象。 輸出格式 1. 函數行為說明 2. 問題列表 3. 最小改動方案這個提示詞的關鍵詞是“保守”和“最小改動”。沒有這兩個詞AI 很容易進入創作模式把簡單函數重構成你覺得高深但項目里沒人能維護的代碼。4.3 模糊指令是代碼變糟糕的根源“幫我優化一下”“讓這段代碼更好”“代碼不夠優雅幫我改進一下”——這類模糊指令是 AI 把代碼改壞的最大原因。為什么因為“優化”沒有度量標準。AI 只能猜測你想要的優化方向。它可能把循環改成 map你可能根本不想引入函數式寫法它可能把多個參數封裝成對象你反而覺得這樣調用更啰嗦。所以每次提需求之前先問自己一個問題這次改動的驗收標準是什么驗收標準是“函數能從 300 行拆成 80 行以內”那任務清晰。驗收標準是“代碼看起來更高級”那任務不清晰請先別讓 AI 動手。清晰的任務描述才可能得到穩定的輸出。模糊的任務描述只會得到隨機的代碼改動。提示詞里出現“提高”“優化”“增強”這類詞時建議同時把“但仍然保持”的約束寫清楚。沒有約束的優化等于讓 AI 自由發揮。5. 驗證 AI 改完的代碼不能只看能不能跑5.1 先逐行看 diff再決定是否合入AI 說你改好了不等于代碼真的改好了。我合入 AI 改動前做的第一件事永遠是看 diff。git diff看 diff 時重點看三類內容一是被刪除的代碼。AI 特別喜歡把一些看起來沒用的 catch 塊、空注釋、舊分支刪掉。這些代碼里有些確實沒用有些是歷史遺留的防御邏輯。刪除之前必須確認真的沒有副作用。二是被新增的抽象層。AI 對“封裝”有天然沖動動不動就新增一個中間層、基類、工廠函數。如果項目里沒有這個習慣建議讓它用最直接的方式寫。三是測試文件的改動。如果一次重構里測試文件也發生了大量修改要特別警惕。正常重構應該保持測試行為不變測試被大面積修改說明實現行為可能變了或者 AI 為了通過測試調整了斷言標準。5.2 測試通過不等于改得對只要項目測試覆蓋足夠測試通過是基本要求。但測試通過并不代表改動就是對的。我一般會在測試通過之后做三輪補充檢查。第一輪是類型檢查。如果有 TypeScript、MyPy、Flow 這類工具一定要跑一遍。AI 改代碼時很容易留下隱式 any、動態屬性或者把類型定義改寬了。npx tsc --noEmit第二輪是 lint。AI 寫的代碼可能風格一致但不一定滿足項目的 lint 規則。跑一遍 lint 能過濾掉大量低級問題。第三輪是手工驗證關鍵路徑。挑一個和這次改動關系最緊密的用戶場景手動跑一遍。比如你改的是登錄模塊就至少跑一遍登錄成功和登錄失敗兩個場景。5.3 三個很容易被 AI 改動帶偏的坑第一個坑是形式主義重構。AI 把代碼拆得很漂亮注釋、命名、空行都很規范但核心邏輯完全沒變甚至比以前更繞。驗收時不要只看結構一定在腦子里過一遍改動前后行為是否一致。第二個坑是過度設計。AI 會為了“可擴展性”引入將來用不到的配置項、策略模式、插件機制。如果項目當前只有一種場景這些抽象就是負擔。約束里可以直接寫不引入新的設計模式不為不存在的需求預留抽象。第三個坑是自我證明幻覺。AI 在解釋自己改動時往往會用非常肯定的語氣描述“這次修復解決了某問題”但代碼未必真的處理了根因。要拿日志、斷點、測試斷言去驗證而不是信它的總結。6. 從單文件到全項目AI Agent 的用法與邊界6.1 適合交給 Agent 的批量任務隨著命令行 AI 編程助手這類工具越來越成熟很多人開始把整項目交給 Agent 處理。這里有一個很重要的判斷邊界有些任務適合有些任務絕對不能適合。我目前愿意交給 Agent 批量執行的任務包括統一替換舊 API。比如某個第三方庫發布了新版本舊函數全部標記 deprecated可以讓 Agent 在項目里自動替換。補類型標注。給 JavaScript 項目遷移 TypeScript 時先讓 Agent 給變量、函數簽名、模塊導出補上基礎類型。批量生成單元測試。對輸入輸出清楚的工具函數Agent 可以用很高的效率生成測試用例。清理 lint 警告。從項目根目錄跑一次 lint把報告里的警告按類型分組分批讓 Agent 處理。整理 TODO 注釋并生成問題清單。這些任務的共同點是規則統一、目標明確、驗證容易。Agent 每次改動之后只要有完整的測試可以跑就能確認是否引入回歸。6.2 不適合交給 Agent 的敏感任務反過來這些任務我堅決不讓 Agent 直接執行架構級重構。比如把單體拆成微服務或者把核心模塊的數據流方向改掉。這種任務需要大量業務上下文和架構判斷Agent 沒有能力也不該負責。安全相關改動。權限模型、認證邏輯、支付流程、敏感數據脫敏這些代碼可以輔助分析但不準直接自動改寫。需要真實用戶反饋的交互流程。比如 UI 狀態的變更、表單校驗規則如果只看代碼AI 可能覺得沒問題但真實用戶會感知到差異。涉及數據遷移的修改。刪字段、改表結構、改緩存 key這類改動一旦出錯恢復成本很高。必須由人設計遷移方案AI 只負責執行它那部分。6.3 用 Agent 之前先畫安全護欄在讓 Agent 真正動項目之前我會先做幾件事。第一確認初始 git 狀態是干凈的所有已有改動都提交到分支上。第二明確 Agent 的工作目錄和可修改文件范圍。不要讓 Agent 隨意在項目根目錄自由發揮。第三檢查 Agent 可能會執行的命令。很多命令行 Agent 會自動安裝依賴、運行腳本、調用外部 API。如果它提出的命令里包含 curl 下載文件、繞過某些檢查、修改權限之類的內容我會手動拒絕并重新評估。一個很通用的安全提醒是不要往終端或開發者工具里粘貼你不理解的代碼。這套邏輯現在同樣適用于 AI 編程——AI 給你的命令如果看不懂它做了什么就不要直接執行。Agent 輔助編程時角色應該是“執行者”而不是“決策者”。決策權必須在你手里。7. 我踩過的坑和現在的使用習慣7.1 三個典型翻車場景翻車場景一過度抽象。有一次清理一個訂單狀態判斷函數我給 AI 的指令是“減少重復代碼”。結果 AI 把函數重構成三個抽象層加了策略模式和狀態映射表。邏輯確實變復雜了但業務可讀性顯著下降最后我放棄了這次改動。后來我意識到重復代碼有時是合理重復尤其當幾處邏輯未來會朝不同方向演化時強行合并反而增加耦合。翻車場景二刪除“無用”代碼。某個歷史遺留的錯誤處理分支AI 判斷它永遠不會執行順手刪掉了。結果三個月后一個極端輸入觸發了空指針。這類問題在代碼審查時很難發現因為刪除動作看起來很小。我的規避方式是所有“刪除冗余代碼”類的請求我都會單獨標注“如果這塊代碼的作用不明確先不要刪標記出來由我決定”。翻車場景三測試全綠但核心路徑沒覆蓋。AI 給一個文件生成了 20 個測試用例全部通過我差點直接合入。后來手工看覆蓋率才發現核心的高風險分支根本沒被測試到。它生成的全是簡單路徑測試。從那以后我只看“測試覆蓋了哪些分支”不再看“測試數量多不多”。7.2 現在的工作流和判斷標準踩過這些坑之后我現在的使用習慣穩定成一套固定流程。第一步給 AI 不超過一個文件的任務目標是生成可驗證的結果。第二步先讓 AI 解釋和列出改動計劃我確認方向后再讓它動代碼。第三步所有改動都必須給出 diff不允許直接覆蓋整個文件。第四步跑構建、測試、類型檢查、lint四關全過才考慮 review。第五步親手跑一遍關鍵業務路徑。第六步合入前看最終 diff確認沒有任何多余改動。這套流程看起來笨但效率其實最高。因為它把每次 AI 改動的風險控制在一個小范圍內真出問題也容易定位和回滾。7.3 適合哪些人用不適合哪些人用最后說適用人群。適合用 AI 改代碼的人至少要能讀懂 AI 的改動。你不一定要成為精通 AI 的工具玩家但你必須能看懂 diff能判斷邏輯是否被改變。這也意味著 AI 改代碼的理想使用者是已經具備一定開發經驗的工程師而不是完全不懂編程、只想讓 AI 自動生成項目的門外漢。不適合的人包括項目本身沒有版本管理和測試改完也不知道是不是壞了。完全不會 review 代碼只能全盤相信 AI 輸出。預期是“丟一個需求進去自動得到完整項目”的人。團隊里沒有人工 review 機制AI 改動可以直接上生產環境。AI 在代碼上的真正價值是幫有判斷力的人把重復勞動吃掉而不是代替人做判斷。我現在的日常狀態是AI 負責把代碼問題暴露出來做批量改動生成測試和文檔我負責看 diff、跑關鍵路徑、做業務決策。這套配合穩定下來之后代碼質量確實在往上走。如果你打算開始嘗試我建議不要從“讓 AI 重構整個項目”開始先找一個小文件、一類問題、一次提交把最小閉環跑通。這個流程一旦熟練再逐步擴大到更復雜的任務會踏實很多。