范:如何讓AI生成代碼更可靠)
1. 為什么 Flutter 項(xiàng)目最先要解決的是 AI 代碼生成的不確定性先說(shuō)個(gè)我曾經(jīng)真實(shí)踩過(guò)的坑。某次給一個(gè)中等規(guī)模的 Flutter 應(yīng)用加離線緩存模塊項(xiàng)目里已經(jīng)有大半代碼是 AI 輔助生成的我圖省事直接把需求描述丟給 Claude Code讓它自己改數(shù)據(jù)層代碼。結(jié)果它非常利索地改完了所有測(cè)試也過(guò)了編譯也沒報(bào)錯(cuò)。當(dāng)時(shí)我還挺滿意后來(lái) Code Review 的時(shí)候發(fā)現(xiàn)一個(gè)問題它把原本項(xiàng)目中統(tǒng)一使用的Either錯(cuò)誤處理風(fēng)格改成了try-catch還把狀態(tài)管理里約定好的StateController命名改成了BlocController整個(gè)代碼風(fēng)格直接分裂了。這個(gè)問題的本質(zhì)不是哪個(gè) AI 工具不行而是工程規(guī)范缺失。AI 生成代碼和人類寫代碼不一樣人類寫代碼會(huì)下意識(shí)跟隨項(xiàng)目現(xiàn)有的風(fēng)格AI 不懂這些項(xiàng)目?jī)?nèi)的潛規(guī)則它只能根據(jù)上下文里的代碼風(fēng)格去猜測(cè)猜不中的時(shí)候就會(huì)產(chǎn)生這類隱蔽的偏差。更麻煩的是這種偏差在編譯期通常看不出來(lái)等代碼合入主分支之后才逐步暴露那時(shí)候再修成本就高了。后來(lái)我搭了一套 Flutter 工程規(guī)范體系核心思路是把項(xiàng)目?jī)?nèi)的代碼風(fēng)格、架構(gòu)約束、命名約定、文件組織規(guī)則都變成 AI 能讀取、能執(zhí)行的顯式規(guī)則再配合 Claude Code 和 Codex 的自動(dòng)化檢查能力讓 AI 在生成代碼的第一時(shí)間就遵守這些規(guī)則。這套方法跑了一段時(shí)間之后AI 生成的代碼質(zhì)量和項(xiàng)目本身代碼的一致性有了明顯提升Code Review 的負(fù)擔(dān)小了很多。這篇文章就把整套搭建思路完完整整地寫出來(lái)包括工具選型、規(guī)則文件怎么寫、Claude Code 和 Codex 怎么配合、以及那些文檔里不會(huì)寫的坑。如果你是 Flutter 開發(fā)者并且已經(jīng)在用 AI 輔助寫代碼或者正準(zhǔn)備引入 AI 編程工具這篇文章應(yīng)該能幫你省下不少返工的時(shí)間。2. 搭規(guī)范前的關(guān)鍵判斷Claude Code 和 Codex 到底各自負(fù)責(zé)什么很多人在同一項(xiàng)目里同時(shí)使用兩個(gè) AI 工具純粹是因?yàn)槊總€(gè)都有點(diǎn)優(yōu)勢(shì)又不舍得放棄另一個(gè)。但如果你不明確它們的分工兩個(gè)工具各寫各的反而會(huì)讓代碼風(fēng)格更混亂。我的做法是讓它們分別負(fù)責(zé)不同的任務(wù)場(chǎng)景并用同一套規(guī)則文件約束輸出。2.1 Claude Code 更適合做重構(gòu)和跨文件修改Claude Code 在處理跨文件的代碼修改、重構(gòu)、架構(gòu)調(diào)整這類任務(wù)時(shí)表現(xiàn)更穩(wěn)因?yàn)樗纳舷挛拇翱诟髮?duì)項(xiàng)目結(jié)構(gòu)的理解更整體。比如把某個(gè)功能模塊從Provider狀態(tài)管理遷移到Riverpod涉及十幾個(gè)文件Claude Code 的表現(xiàn)通常比 Codex 更可靠。對(duì)于這類任務(wù)我給它配置的規(guī)則重點(diǎn)是保持原有公共接口不變遷移時(shí)保留原有測(cè)試用例所有新增依賴必須聲明在 pubspec.yaml 中。有了這些約束它做重構(gòu)的時(shí)候會(huì)更謹(jǐn)慎。2.2 Codex 更適合做小范圍功能生成和代碼補(bǔ)全Codex 的優(yōu)勢(shì)在于輕快、便宜適合完成明確的小任務(wù)比如寫一個(gè)根據(jù)傳入?yún)?shù)生成分頁(yè)列表的 Widget實(shí)現(xiàn)一個(gè)從 JSON 解析用戶模型的 fromJson 方法這類范圍清晰的代碼生成。它生成代碼速度快在小范圍的獨(dú)立文件修改上質(zhì)量很不錯(cuò)。Codex 的風(fēng)險(xiǎn)在于它不像 Claude Code 那么了解整個(gè)項(xiàng)目的上下文所以規(guī)則文件對(duì)它更重要。比如它可能不認(rèn)識(shí)項(xiàng)目里自定義的基礎(chǔ)組件AppBaseWidget直接在代碼里新建了一個(gè)類似的容器組件這種問題只能靠規(guī)則約束。2.3 兩份獨(dú)立規(guī)則文件的配置結(jié)構(gòu)我建議不要只維護(hù)一份通用的規(guī)則文件而是為兩個(gè)工具分別維護(hù)。原因是它們的配置讀取機(jī)制不同可用的規(guī)則描述能力也不同。我的配置結(jié)構(gòu)是Claude Code 使用項(xiàng)目根目錄下的CLAUDE.md文件它每次會(huì)話開始時(shí)會(huì)自動(dòng)讀取Codex 使用項(xiàng)目根目錄下的AGENTS.md文件或者在使用時(shí)通過(guò)-f參數(shù)指定規(guī)則文件。兩條工具默認(rèn)讀取的文件不同所以我們分別維護(hù)同時(shí)把一份共享的工程規(guī)范核心內(nèi)容放在兩個(gè)文件里。這樣每個(gè)工具體系獨(dú)立但規(guī)范核心一致。提示如果你用 Codex 的本地命令行版本每次執(zhí)行時(shí)加-f AGENTS.md參數(shù)指定規(guī)則文件避免它因?yàn)槟夸泦栴}沒讀到規(guī)范。這一點(diǎn)實(shí)操中很容易踩坑。2.4 統(tǒng)一規(guī)范核心避免規(guī)則漂移兩個(gè)文件雖然分開維護(hù)但核心規(guī)范必須一致否則會(huì)出現(xiàn) Claude Code 寫的代碼遵守一套規(guī)則、Codex 遵守另一套的情況。我解決這個(gè)問題的辦法是把規(guī)范內(nèi)容集中寫在項(xiàng)目根目錄的docs/engineering_guidelines.md文件里CLAUDE.md和AGENTS.md里只寫一句請(qǐng)嚴(yán)格遵守docs/engineering_guidelines.md中的全部規(guī)范。這樣只需要維護(hù)一份源文檔既避免了多份文件不同步的問題也方便項(xiàng)目里的真人開發(fā)者閱讀同一份規(guī)范。3. 工程規(guī)范文件的核心內(nèi)容讓 AI 能聽懂 Flutter 項(xiàng)目的約束規(guī)范文件要想真正起作用不能只寫代碼風(fēng)格保持一致這種模糊的話AI 需要的是可執(zhí)行的、具體的規(guī)則。我按照 Flutter 項(xiàng)目的工程特征把規(guī)范拆成了七大塊每塊都有明確的描述和正反示例下面逐一說(shuō)明。3.1 項(xiàng)目架構(gòu)與目錄結(jié)構(gòu)約束Flutter 項(xiàng)目的架構(gòu)風(fēng)格直接決定了 AI 生成的文件應(yīng)該放在哪里。如果你的項(xiàng)目用的是 feature-first 架構(gòu)那么 AI 生成的模塊文件就必須放進(jìn)對(duì)應(yīng)功能目錄否則整個(gè)目錄會(huì)成為大雜燴。我通常會(huì)在規(guī)范文件里寫明項(xiàng)目采用 feature-first 目錄結(jié)構(gòu) lib/features/feature_name/ ├── data/ (數(shù)據(jù)源、倉(cāng)儲(chǔ)實(shí)現(xiàn)) ├── domain/ (實(shí)體、倉(cāng)儲(chǔ)接口、用例) └── presentation/ (頁(yè)面、組件、狀態(tài)管理) 新增功能代碼必須放入對(duì)應(yīng)模塊目錄禁止在 lib/ 根目錄直接創(chuàng)建新文件夾。 共享組件放入 lib/shared/widgets/共享工具類放入 lib/shared/utils/。同時(shí)我在規(guī)范里明確寫出禁止事項(xiàng)禁止在 main.dart 中直接寫業(yè)務(wù)邏輯main.dart 只負(fù)責(zé)初始化與路由配置。這類否定式約束對(duì) AI 特別有效因?yàn)?AI 傾向于在描述性的規(guī)則下自行發(fā)揮而否定式規(guī)則能直接阻斷它跑偏。3.2 狀態(tài)管理方案的統(tǒng)一約束Flutter 生態(tài)里的狀態(tài)管理方案非常多項(xiàng)目一旦選定就必須堅(jiān)持否則 AI 會(huì)因?yàn)槿蝿?wù)描述里的某個(gè)詞匯就切換方案。我見過(guò)最典型的場(chǎng)景任務(wù)里提到這個(gè)頁(yè)面需要一個(gè)加載狀態(tài)AI 就直接引入了一套額外的 loading 方案代碼而項(xiàng)目本身已經(jīng)有統(tǒng)一的 loading 框架。我的規(guī)范文件里會(huì)明確寫當(dāng)前的狀態(tài)管理方案并強(qiáng)調(diào)禁止引入新的狀態(tài)管理庫(kù)。本項(xiàng)目使用 Riverpod 作為唯一狀態(tài)管理方案。 - 頁(yè)面狀態(tài)用 StateProvider 或 NotifierProvider禁止使用 setState 處理跨組件狀態(tài)。 - 異步加載場(chǎng)景統(tǒng)一使用 AsyncValue 處理禁止在 Widget 內(nèi)部手動(dòng)管理多個(gè) loading 標(biāo)志位。 - 團(tuán)隊(duì)已封裝 AppAsyncBuilder 組件禁止使用其他方式渲染異步狀態(tài)。配上一個(gè)反面示例如果看到語(yǔ)言為setState的代碼必須重寫為 Riverpod 的NotifierProvider并同步調(diào)整測(cè)試代碼。正反結(jié)合AI 生成代碼時(shí)不會(huì)摸不著頭腦。3.3 命名規(guī)范與代碼風(fēng)格Dart 自帶官方風(fēng)格指南但項(xiàng)目里通常還會(huì)有團(tuán)隊(duì)自己的約定比如私有文件用_前綴、某些特定類型組件用固定后綴等。這些約定要逐條寫上。我自己常用的幾條約束是組件類名使用PascalCase文件名使用snake_case但 StatefulWidget 的 State 類命名為_XxxState頁(yè)面級(jí) Widget 統(tǒng)一使用后綴Page業(yè)務(wù)組件統(tǒng)一使用后綴Widget比如LoginPage、UserCardWidget枚舉類型文件名加_enum后綴數(shù)據(jù)模型文件名加_model后綴JSON 解析方法統(tǒng)一命名為fromJson/toJson禁止使用fromMap/toMap常量直接使用abstract final class定義在lib/shared/constants/目錄下禁止在頁(yè)面文件里散落魔法數(shù)字。這些規(guī)則看似瑣碎但正是這些細(xì)節(jié)最需要 AI 遵守。任何一個(gè)不一致的小命名在 Flutter 項(xiàng)目里都會(huì)成為 Code Review 的一項(xiàng)糾錯(cuò)點(diǎn)積累多了會(huì)非常影響效率。3.4 依賴注入方式Flutter 項(xiàng)目的 DI依賴注入一般有兩種主流方式使用provider包手動(dòng)注入或者使用riverpod自帶的容器機(jī)制。規(guī)范里明確寫清楚 DI 寫法能避免 AI 生成出無(wú)法編譯的代碼。我指定了如下的依賴注入模式禁止在 Widget 構(gòu)造函數(shù)中傳遞 Repository 依賴統(tǒng)一使用 Riverpod 的 Provider 完成依賴注入。 新增的數(shù)據(jù)源、倉(cāng)儲(chǔ)、用例類必須在對(duì)應(yīng)的 provider 文件中完成注冊(cè)。 Provider 文件位于 lib/features/feature_name/di/ 目錄。這條規(guī)范特別重要。有一次 Codex 生成一個(gè)新的登錄頁(yè)面它把所有依賴都通過(guò)構(gòu)造函數(shù)傳參傳遞了代碼編譯沒問題但完全破壞了整個(gè)項(xiàng)目的依賴注入結(jié)構(gòu)后來(lái)我花了半天時(shí)間才把它改成 Provider 注入的方式?,F(xiàn)在規(guī)范文件里明確約束之后同類問題基本沒有再出現(xiàn)過(guò)。3.5 數(shù)據(jù)層與網(wǎng)絡(luò)層規(guī)范Flutter 項(xiàng)目里最容易出問題的是網(wǎng)絡(luò)請(qǐng)求和數(shù)據(jù)解析部分因?yàn)檫@里涉及的代碼模式多AI 可能生成多種不同的寫法。我要求的統(tǒng)一模式是所有網(wǎng)絡(luò)請(qǐng)求統(tǒng)一使用項(xiàng)目封裝的ApiClient類禁止直接使用dio或http裸調(diào)用接口返回?cái)?shù)據(jù)統(tǒng)一先經(jīng)過(guò)ApiResponseT包裝再解析到模型模型必須包含fromJson和copyWith方法所有后端接口的路徑常量定義在lib/shared/constants/api_paths.dart禁止在業(yè)務(wù)代碼中直接寫 URL 字符串?!敖怪苯邮褂?dio 裸調(diào)用”這條我在實(shí)踐中發(fā)現(xiàn)必須寫得非常直白。AI 在生成網(wǎng)絡(luò)請(qǐng)求代碼時(shí)非常傾向直接把dio.get(...)寫在業(yè)務(wù)代碼里面但它不知道項(xiàng)目里已經(jīng)有封裝好的ApiClient。規(guī)范里明確禁止之后AI 就會(huì)主動(dòng)去找ApiClient并調(diào)用它。3.6 錯(cuò)誤處理與日志規(guī)范錯(cuò)誤處理風(fēng)格混亂是 AI 生成代碼的另一個(gè)重災(zāi)區(qū)。有的地方用try-catch有的地方用Either有的地方直接拋異常但不處理。我要求全項(xiàng)目統(tǒng)一使用Result模式業(yè)務(wù)層禁止直接使用 try-catch 捕獲異常統(tǒng)一返回 ResultT sealed class ResultT { ... } 所有有可能失敗的調(diào)用都必須返回 Result 類型由調(diào)用方顯式處理成功與失敗分支。 持久化與框架層代碼可以使用 try-catch但捕獲后必須記錄日志禁止靜默吞掉異常。 日志統(tǒng)一通過(guò) Logger 工具輸出禁止使用 print。這條規(guī)范特別考驗(yàn) AI 的理解能力。實(shí)際上 Claude Code 在處理這種sealed class 模式時(shí)通常表現(xiàn)良好它能理解文檔里對(duì)失敗分支處理的描述而 Codex 有時(shí)會(huì)在非常短的代碼片段里漏掉失敗分支處理所以需要配合下面的自動(dòng)化檢查來(lái)兜底。3.7 測(cè)試規(guī)范約束很多 Flutter 開發(fā)者不在意 AI 是否生成測(cè)試但如果你想讓 AI 長(zhǎng)期參與項(xiàng)目開發(fā)測(cè)試規(guī)范必須從一開始就立好。我的要求是新增功能模塊必須配套單元測(cè)試測(cè)試文件放在 test/ 目錄下并且與模塊目錄結(jié)構(gòu)保持一致。 測(cè)試使用 mockito 或 fake 對(duì)象禁止依賴真實(shí)網(wǎng)絡(luò)請(qǐng)求。 測(cè)試命名遵循 given/when/then 風(fēng)格。AI 生成測(cè)試代碼的能力很強(qiáng)特別是 Claude Code它通常能生成覆蓋主干路徑的測(cè)試但如果規(guī)范里沒有要求它不會(huì)主動(dòng)寫。現(xiàn)在這套規(guī)范跑下來(lái)AI 生成的功能代碼基本能同步生成測(cè)試測(cè)試覆蓋率在新增代碼上維持在 85% 以上差不多是真人開發(fā)的水平了。4. 讓規(guī)范真正被執(zhí)行Claude Code 和 Codex 的聯(lián)動(dòng)工作流規(guī)則文件寫好了但如果只是放在那里AI 未必每次都會(huì)完整遵守尤其是復(fù)雜任務(wù)下容易忘掉某些規(guī)則。所以我在規(guī)范文件之外還搭了一層聯(lián)動(dòng)工作流讓兩個(gè)工具互相檢查效果比單獨(dú)依賴某一款工具好得多。4.1 開發(fā)流程Claude Code 主寫主審Codex 負(fù)責(zé)快速生成我運(yùn)用這套體系有三個(gè)月了以下是目前穩(wěn)定運(yùn)行的流程整個(gè)過(guò)程分三步需求拆解后先把任務(wù)交給 Claude Code給它完整的上下文包括涉及的功能模塊、現(xiàn)有的關(guān)聯(lián)代碼、必須遵守的規(guī)范條款簡(jiǎn)單生成任務(wù)交給 Codex 快速完成。比如寫一個(gè)PaginationList組件支持加載更多和刷新功能按規(guī)范命名放在指定目錄Claude Code 生成完主代碼后由 Codex 執(zhí)行一輪獨(dú)立的代碼審查檢查它是否違反了規(guī)范文件中的內(nèi)容。為什么要用兩個(gè)工具互相審查因?yàn)?AI 審查 AI 的代碼和人類審查 AI 的代碼不一樣AI 有一個(gè)巨大的優(yōu)勢(shì)它極其擅長(zhǎng)識(shí)別模式偏差。比如命名風(fēng)格不一致、某個(gè)錯(cuò)誤處理方式偏離規(guī)范這些在 Codex 審查時(shí)能被快速定位。4.2 Codex 執(zhí)行規(guī)范審查的 Prompt 模板審查環(huán)節(jié)的 prompt 我攢了一套模板實(shí)測(cè)效果很好直接貼出來(lái)給你參考你是本項(xiàng)目的高級(jí) Flutter 工程師。請(qǐng)嚴(yán)格按照 docs/engineering_guidelines.md 中的規(guī)范審查以下文件并只輸出發(fā)現(xiàn)的問題列表 [文件路徑列表] 要求 1. 只報(bào)告違反規(guī)范的問題不要修改代碼 2. 對(duì)每個(gè)問題標(biāo)明違反的具體規(guī)范條目編號(hào) 3. 如果沒有問題輸出通過(guò)檢查。這套 prompt 的關(guān)鍵點(diǎn)是只輸出問題列表不要讓它直接修。因?yàn)?AI 一旦自己動(dòng)手改它會(huì)傾向于重寫整個(gè)文件這往往會(huì)引入新的不規(guī)范代碼。讓它只列出問題我們?cè)贈(zèng)Q定是讓 Claude Code 修改還是手動(dòng)修改。4.3 人工 Review 的兜底時(shí)機(jī)你可能會(huì)問既然 AI 互審了還需要人工 Review 嗎。我的回答是需要但人的負(fù)擔(dān)可以大幅減輕。我現(xiàn)在的流程是AI 互審全部通過(guò)之后我再自己看一遍 diff重點(diǎn)看這三類內(nèi)容業(yè)務(wù)邏輯是否有遺漏、邊界條件是否處理到位、UI 細(xì)節(jié)是否符合設(shè)計(jì)稿。而關(guān)于代碼風(fēng)格是否符合規(guī)范這類問題我基本不再花時(shí)間檢查了因?yàn)?AI 互審已經(jīng)能比較可靠地兜住這方面問題。這套聯(lián)動(dòng)流程跑下來(lái)我個(gè)人的 Code Review 時(shí)間減少了至少一半。4.4 小改動(dòng)怎么處理有人可能會(huì)擔(dān)心如果只是改一個(gè)方法兩三行代碼也走這套流程是不是太重了。我的建議是小改動(dòng)直接手動(dòng)改不進(jìn) AI 流程凡是新增文件或改動(dòng)超過(guò)三十行都必須走上述聯(lián)動(dòng)。這套工作流的成本并不高但對(duì)于大改動(dòng)它的價(jià)值是實(shí)打?qū)嵉?。如果需要改?dòng)多個(gè)文件再給 Claude Code 一次性的完整變更指令讓它一次改完效率更高。5. 自動(dòng)化檢查層讓規(guī)范違反問題在代碼提交前就被攔下規(guī)則文件和工作流解決的是AI 生成時(shí)遵守規(guī)范的問題但 AI 偶爾還是會(huì)出現(xiàn)意外。所以我又加了一層自動(dòng)化檢查確保任何違反規(guī)范的代碼在提交之前就被攔下來(lái)。這部分用的是 Dart 生態(tài)里的標(biāo)準(zhǔn)工具加上 CI 配置。5.1 基礎(chǔ)檢查組合analyze format testFlutter 項(xiàng)目基礎(chǔ)的三件套是繞不開的dart analyze靜態(tài)分析能查出大部分編碼問題dart format --set-exit-if-changed檢查代碼格式是否符合規(guī)范flutter test跑測(cè)試防止邏輯回歸。這三項(xiàng)我全部掛在 CI 上任何 PR 未通過(guò)檢查都不能合并。AI 生成的代碼往往在小細(xì)節(jié)上會(huì)在這三項(xiàng)上翻車比如工具自動(dòng)生成的格式和項(xiàng)目格式化配置不一致dart format就能直接體現(xiàn)問題。有一點(diǎn)要注意格式檢查跑在 CI 上沒意義因?yàn)殚_發(fā)機(jī)上可以一鍵格式化但 CI 上失敗只會(huì)增加一次提交輪次。它可以作為規(guī)范的兜底但不能是唯一的反饋途徑。5.2 自定義架構(gòu)掃描腳本標(biāo)準(zhǔn)檢查之外我還寫了一個(gè)自定義的 Dart 腳本tool/check_arch.dart專門掃描項(xiàng)目結(jié)構(gòu)是否符合規(guī)范。這個(gè)腳本做的事情很機(jī)械但很實(shí)用檢查lib/features/下是否有不符合 feature-first 目錄結(jié)構(gòu)的新建目錄檢查是否有業(yè)務(wù)代碼引用dio或http包進(jìn)行網(wǎng)絡(luò)請(qǐng)求檢查是否有代碼在lib/下直接定義常量而沒有放入lib/shared/constants/檢查是否有頁(yè)面類沒有使用Page后綴。這個(gè)腳本我沒做得多復(fù)雜幾百行 Dart 代碼用了analyzer包的基礎(chǔ) API遍歷 AST 做字符串和模式匹配。丟到 CI 上跑了這段時(shí)間效果出奇地好——它抓到的規(guī)范違反案例比人工 Code Review 更全面因?yàn)樵诖a量大的情況下人工很難逐行注意到所有細(xì)節(jié)。5.3 CI 執(zhí)行鏈的完整配置示例最后放一個(gè)我目前正在使用的 CI 配置片段使用常見 CI 平臺(tái)的語(yǔ)法格式你可以直接抄過(guò)去改改jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: subosito/flutter-actionv2 with: channel: stable - run: flutter pub get - run: dart analyze - run: dart format --set-exit-if-changed . - run: flutter test --coverage - run: dart tool/check_arch.dart有了這條鏈子每次提交 AI 生成的代碼先過(guò)自動(dòng)檢查再過(guò) AI 互審最后才到人工 Review。檢查的等級(jí)是層層遞進(jìn)的前一層通過(guò)之后后面一層的效率就能大幅提升。5.4 自動(dòng)化檢查遇到的常見坑最后提醒兩個(gè)坑。第一個(gè)是dart format和編輯器格式化配置不一致的問題我遇到過(guò) CI 上格式檢查失敗但本地 IDE 顯示格式一切正常后來(lái)發(fā)現(xiàn)是項(xiàng)目里缺了analysis_options.yaml中對(duì)formatter的配置。解決方法是在項(xiàng)目里固定一個(gè)dart format配置版本并確保團(tuán)隊(duì)所有人都使用同一版本的 Flutter SDK。第二個(gè)坑是自定義掃描腳本容易誤報(bào)。比如某些第三方包源碼里本來(lái)就有dio依賴腳本掃描的時(shí)候會(huì)把第三方代碼也算進(jìn)去。解決辦法是在腳本里增加排除規(guī)則只掃描lib/目錄不掃描第三方包緩存目錄。6. 這套規(guī)范體系的實(shí)際效果從參數(shù)到可量化的收益說(shuō)了這么多最后把效果量化一下畢竟沒有數(shù)據(jù)支撐的方法論很難讓團(tuán)隊(duì)接受。6.1 代碼風(fēng)格統(tǒng)一度提升配置這套規(guī)范之前AI 生成的代碼和項(xiàng)目既有代碼的風(fēng)格一致性大概是這樣AI 能看懂文件里的局部風(fēng)格但跨文件的統(tǒng)一約定基本靠運(yùn)氣。配置之后我抽了幾次項(xiàng)目的代碼做了統(tǒng)計(jì)AI 生成代碼的風(fēng)格違反率從早期的 15% 左右降到了 3% 以下。這個(gè)數(shù)字說(shuō)明規(guī)范文件本身就有相當(dāng)強(qiáng)的約束力加上自動(dòng)化檢查的兜底AI 生成代碼的偏差基本被控制到了可以接受的范圍。6.2 Code Review 效率提升之前每次 Code Review AI 生成的代碼平均要花 45 分鐘到一個(gè)小時(shí)其中大部分時(shí)間是在糾正風(fēng)格和結(jié)構(gòu)問題真正的業(yè)務(wù)邏輯審查反而沒時(shí)間細(xì)看?,F(xiàn)在 AI 互審和自動(dòng)化檢查把結(jié)構(gòu)問題都攔在了前面我的 Review 時(shí)間壓縮到 20 分鐘以內(nèi)而且這 20 分鐘可以完全專注在業(yè)務(wù)邏輯上。團(tuán)隊(duì)里的 A 同學(xué)之前對(duì) AI 生成代碼很不信任覺得每次都要重新改一遍。這套流程跑了一個(gè)多月之后他主動(dòng)說(shuō)現(xiàn)在 AI 提交的代碼質(zhì)量有時(shí)候比自己手寫的還穩(wěn)定至少命名和目錄結(jié)構(gòu)從來(lái)不用操心了。6.3 返工率下降量化返工率可能有點(diǎn)難但有一個(gè)簡(jiǎn)單的觀測(cè)指標(biāo)合并之后因?yàn)榇a規(guī)范問題而被回滾的 PR 數(shù)量。之前平均兩三個(gè) PR 就會(huì)有一個(gè)因?yàn)橐?guī)范問題被退回這套體系上線之后最近兩個(gè)月基本沒出現(xiàn)過(guò)因?yàn)橐?guī)范問題導(dǎo)致的回滾。這個(gè)改善對(duì)團(tuán)隊(duì)信任度的提升很明顯大家開始愿意讓 AI 承擔(dān)更多的編碼任務(wù)。6.4 這套體系的維護(hù)成本當(dāng)然也要說(shuō)說(shuō)不好的方面。規(guī)范的維護(hù)是有成本的隨著項(xiàng)目演進(jìn)規(guī)范文件本身要持續(xù)更新新增依賴時(shí)需要評(píng)估它是否影響現(xiàn)有規(guī)范CI 腳本如果項(xiàng)目結(jié)構(gòu)調(diào)整了也需要跟著改。好在這套東西的維護(hù)頻率不高大概一兩個(gè)迭代周期才需要更新一次完全可以接受。7. 關(guān)于AI 生成代碼到底能不能用于生產(chǎn)項(xiàng)目的一點(diǎn)個(gè)人體會(huì)最后說(shuō)點(diǎn)個(gè)人體會(huì)不談方法論。我之前對(duì) AI 生成代碼的態(tài)度經(jīng)歷了一個(gè)變化一開始完全不信任后來(lái)覺得它寫小段代碼挺好用的但不敢讓它碰大文件直到搭完這套規(guī)范體系我才覺得 AI 代碼生成可以真正進(jìn)入日常開發(fā)流程。它解決的問題不是AI 能不能寫出正確代碼——這個(gè)問題的答案早就人盡皆知了真正的問題是AI 能不能持續(xù)產(chǎn)出符合團(tuán)隊(duì)規(guī)范的代碼。搭規(guī)范的過(guò)程本質(zhì)上是把團(tuán)隊(duì)里很多心照不宣的隱性知識(shí)顯性化。我自己在寫規(guī)范文件的過(guò)程中也重新審視了一遍項(xiàng)目的代碼組織方式發(fā)現(xiàn)了幾個(gè)之前一直靠口頭提醒的約定如今終于被寫成了可執(zhí)行的內(nèi)容。這種沉淀即使沒有 AI對(duì)項(xiàng)目本身也是有好處的。再分享一個(gè)小技巧規(guī)范文件不要一次性寫太長(zhǎng)第一次先寫核心的二十條跑兩個(gè)迭代之后再根據(jù)實(shí)際出現(xiàn)的問題把新的規(guī)則補(bǔ)進(jìn)去。AI 規(guī)范文件不是法律條文它更像一個(gè)項(xiàng)目的操作手冊(cè)需要持續(xù)迭代才能貼合項(xiàng)目的真實(shí)狀態(tài)。如果你也在糾結(jié)AI 寫代碼靠不靠譜這個(gè)問題我建議先把規(guī)范搭起來(lái)再說(shuō)。工具選擇哪家倒是其次真正的核心是你愿不愿意花點(diǎn)時(shí)間把團(tuán)隊(duì)里那些默認(rèn)大家都懂的約定一條一條地寫清楚。條條寫清楚了AI 自然就不會(huì)亂來(lái)。