“看著對(duì),其實(shí)錯(cuò)”)
文章目錄一、能運(yùn)行不代表正確二、AI 為什么會(huì)生成“看著對(duì)”的代碼1. 缺少業(yè)務(wù)上下文2. 使用了看似合理的 API3. 忽略了邊界條件4. 把示例代碼誤當(dāng)成生產(chǎn)代碼三、一個(gè)典型的錯(cuò)誤案例四、生成代碼后先檢查什么第一步重新閱讀需求第二步找出 AI 做的假設(shè)第三步準(zhǔn)備最小測(cè)試集第四步檢查項(xiàng)目環(huán)境五、四種常見(jiàn)錯(cuò)誤要重點(diǎn)防范1. 邏輯正確業(yè)務(wù)錯(cuò)誤2. 正常數(shù)據(jù)正確異常數(shù)據(jù)出錯(cuò)3. 本地可用項(xiàng)目中不可用4. 功能正確但存在安全問(wèn)題六、讓 AI 幫你驗(yàn)證而不是只讓它生成七、不要只看 AI 的解釋八、AI 生成代碼驗(yàn)收清單總結(jié)?創(chuàng)作者全棧弄潮兒 個(gè)人主頁(yè)全棧弄潮兒的個(gè)人主頁(yè)? 個(gè)人社區(qū)歡迎你的加入全棧開(kāi)發(fā)社區(qū) 專(zhuān)欄地址AI 編程提效實(shí)戰(zhàn)使用 AI 寫(xiě)代碼時(shí)我們經(jīng)常會(huì)遇到一種情況代碼格式很完整。變量命名看起來(lái)很規(guī)范。沒(méi)有明顯的語(yǔ)法錯(cuò)誤。運(yùn)行簡(jiǎn)單示例也能得到結(jié)果。但是放到真實(shí)項(xiàng)目中卻出現(xiàn)了問(wèn)題。這就是“看著對(duì)其實(shí)錯(cuò)”。問(wèn)題不一定是 AI 不會(huì)寫(xiě)代碼而是 AI 給出的代碼通常基于已有信息進(jìn)行推測(cè)。如果需求、項(xiàng)目上下文或驗(yàn)證過(guò)程不完整代碼就可能與真實(shí)目標(biāo)不一致。這篇文章重點(diǎn)解決一個(gè)問(wèn)題AI 生成代碼后我們應(yīng)該如何判斷它到底能不能用一、能運(yùn)行不代表正確代碼的正確性至少包含四個(gè)層面檢查層面需要確認(rèn)的問(wèn)題語(yǔ)法代碼能不能被正確解析運(yùn)行執(zhí)行時(shí)會(huì)不會(huì)報(bào)錯(cuò)邏輯結(jié)果是否符合業(yè)務(wù)規(guī)則工程是否安全、可維護(hù)、不會(huì)影響其他功能很多人只檢查了前兩項(xiàng)代碼沒(méi)有語(yǔ)法錯(cuò)誤也可以正常運(yùn)行。但真正容易出問(wèn)題的往往是后兩項(xiàng)。例如一個(gè)計(jì)算折扣的函數(shù)即使能夠正常返回?cái)?shù)字也不代表折扣計(jì)算一定正確。二、AI 為什么會(huì)生成“看著對(duì)”的代碼1. 缺少業(yè)務(wù)上下文同一個(gè)字段在不同項(xiàng)目中可能有不同含義。例如discount可能表示0.2代表打八折。20代表優(yōu)惠 20%。2000代表優(yōu)惠金額 2000 元。如果只告訴 AI“寫(xiě)一個(gè)計(jì)算折扣的函數(shù)”它無(wú)法確定這個(gè)字段的真實(shí)含義只能按照常見(jiàn)寫(xiě)法進(jìn)行猜測(cè)。2. 使用了看似合理的 APIAI 可能會(huì)生成一個(gè)名稱(chēng)合理的函數(shù)或者使用一個(gè)已經(jīng)過(guò)時(shí)的 API。代碼看起來(lái)符合某個(gè)框架的風(fēng)格但當(dāng)前項(xiàng)目版本可能并不支持它。因此看到 AI 使用陌生方法時(shí)應(yīng)該通過(guò)項(xiàng)目文檔、類(lèi)型定義或官方文檔進(jìn)行確認(rèn)。3. 忽略了邊界條件AI 生成的代碼通常先滿(mǎn)足正常輸入。但真實(shí)項(xiàng)目還需要考慮空值。負(fù)數(shù)。0。最大值和最小值。小數(shù)精度。錯(cuò)誤類(lèi)型。重復(fù)操作。網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)異常。如果沒(méi)有明確提出這些要求AI 可能不會(huì)主動(dòng)完整處理。4. 把示例代碼誤當(dāng)成生產(chǎn)代碼為了說(shuō)明思路AI 有時(shí)會(huì)省略參數(shù)校驗(yàn)。權(quán)限檢查。日志處理。錯(cuò)誤處理。超時(shí)和重試。數(shù)據(jù)庫(kù)事務(wù)。示例代碼適合幫助我們理解方向但不能直接等同于可以上線(xiàn)的代碼。三、一個(gè)典型的錯(cuò)誤案例假設(shè)業(yè)務(wù)需求是商品價(jià)格以元為單位。discount傳入整數(shù)百分比。discount: 20表示優(yōu)惠 20%。折后價(jià)格不能小于 0。價(jià)格結(jié)果保留兩位小數(shù)。我們讓 AI 生成函數(shù)functioncalculateFinalPrice(price,discount){returnprice*(1-discount);}這段代碼看起來(lái)很簡(jiǎn)潔但執(zhí)行下面的代碼console.log(calculateFinalPrice(100,20));結(jié)果是-1900原因是代碼把20當(dāng)成了20.0而不是20%。正確的計(jì)算方式應(yīng)該先將百分比轉(zhuǎn)換成小數(shù)functioncalculateFinalPrice(price,discount){if(!Number.isFinite(price)||price0){thrownewError(price 必須是大于等于 0 的數(shù)字);}if(!Number.isFinite(discount)||discount0||discount100){thrownewError(discount 必須是 0 到 100 之間的數(shù)字);}constfinalPriceprice*(1-discount/100);returnNumber(finalPrice.toFixed(2));}這段代碼仍然需要根據(jù)項(xiàng)目實(shí)際規(guī)則進(jìn)行確認(rèn)但至少處理了幾個(gè)關(guān)鍵問(wèn)題明確discount的單位是百分比。檢查價(jià)格和折扣是否為有效數(shù)字。防止折扣小于 0 或大于 100。對(duì)金額結(jié)果進(jìn)行精度處理。這個(gè)例子說(shuō)明AI 不一定寫(xiě)錯(cuò)了語(yǔ)法但可能理解錯(cuò)了字段含義。四、生成代碼后先檢查什么第一步重新閱讀需求不要拿到代碼后馬上運(yùn)行先對(duì)照需求檢查輸入?yún)?shù)的類(lèi)型是否正確。字段單位是否正確。返回值是否符合約定。成功條件是否完整。失敗時(shí)應(yīng)該如何處理。是否包含權(quán)限和安全要求。尤其要關(guān)注金額、時(shí)間、比例、狀態(tài)值和 ID 這類(lèi)容易產(chǎn)生歧義的字段。第二步找出 AI 做的假設(shè)可以直接問(wèn) AI請(qǐng)列出你生成這段代碼時(shí)做出的所有假設(shè)。 重點(diǎn)檢查 1. 每個(gè)參數(shù)的類(lèi)型和單位 2. 空值和異常值的處理方式 3. 時(shí)間、金額和比例的計(jì)算規(guī)則 4. 依賴(lài)的庫(kù)和版本 5. 權(quán)限和安全前提 不要修改代碼只列出假設(shè)和可能需要確認(rèn)的問(wèn)題。這一步很有用因?yàn)殡[藏的假設(shè)往往就是錯(cuò)誤的來(lái)源。第三步準(zhǔn)備最小測(cè)試集至少準(zhǔn)備四類(lèi)輸入測(cè)試類(lèi)型示例目的正常值價(jià)格 100折扣 20檢查主要流程邊界值折扣 0、100檢查最小和最大范圍異常值空值、字符串、負(fù)數(shù)檢查參數(shù)校驗(yàn)極端值很大的價(jià)格和小數(shù)檢查精度和穩(wěn)定性對(duì)應(yīng)到前面的函數(shù)可以先寫(xiě)出測(cè)試console.log(calculateFinalPrice(100,20));console.log(calculateFinalPrice(100,0));console.log(calculateFinalPrice(100,100));try{calculateFinalPrice(100,120);}catch(error){console.log(error.message);}預(yù)期結(jié)果應(yīng)該是80 100 0 discount 必須是 0 到 100 之間的數(shù)字測(cè)試不是為了證明 AI 一定正確而是為了盡快暴露錯(cuò)誤。第四步檢查項(xiàng)目環(huán)境代碼從單獨(dú)示例放進(jìn)項(xiàng)目后還要確認(rèn)使用的庫(kù)是否已經(jīng)安裝。導(dǎo)入方式是否符合當(dāng)前版本。項(xiàng)目是否使用 TypeScript 類(lèi)型約束。返回格式是否符合現(xiàn)有接口。日志和錯(cuò)誤處理是否符合項(xiàng)目規(guī)范。是否需要補(bǔ)充單元測(cè)試。如果 AI 使用了項(xiàng)目中不存在的函數(shù)或依賴(lài)不能為了讓代碼運(yùn)行就隨意安裝新包。先確認(rèn)項(xiàng)目是否已經(jīng)有同類(lèi)能力。五、四種常見(jiàn)錯(cuò)誤要重點(diǎn)防范1. 邏輯正確業(yè)務(wù)錯(cuò)誤代碼按照某種邏輯運(yùn)行但不符合產(chǎn)品規(guī)則。例如把自然日當(dāng)成工作日計(jì)算。把“優(yōu)惠 20%”理解成“價(jià)格乘以 20%”。把訂單狀態(tài)1當(dāng)成已完成但項(xiàng)目中1表示待支付。把用戶(hù)的本地時(shí)間當(dāng)成服務(wù)器時(shí)間。這類(lèi)問(wèn)題只能通過(guò)需求、接口文檔和業(yè)務(wù)示例確認(rèn)不能只看語(yǔ)法。2. 正常數(shù)據(jù)正確異常數(shù)據(jù)出錯(cuò)例如搜索功能在輸入關(guān)鍵字時(shí)正常但輸入空字符串、特殊字符或超長(zhǎng)字符串時(shí)發(fā)生異常。需要主動(dòng)測(cè)試空字符串。只有空格的字符串。特殊字符。超長(zhǎng)內(nèi)容。不符合類(lèi)型的參數(shù)。3. 本地可用項(xiàng)目中不可用常見(jiàn)原因包括AI 使用了錯(cuò)誤的框架版本。本地示例依賴(lài)了未安裝的包。環(huán)境變量名稱(chēng)不一致。接口字段與項(xiàng)目約定不同。沒(méi)有考慮真實(shí)的異步和權(quán)限流程。因此生成代碼后必須放回真實(shí)項(xiàng)目運(yùn)行而不是只在獨(dú)立代碼片段中測(cè)試。4. 功能正確但存在安全問(wèn)題代碼能實(shí)現(xiàn)功能不代表可以安全使用。需要重點(diǎn)檢查是否直接拼接 SQL。是否把用戶(hù)輸入插入 HTML。是否繞過(guò)權(quán)限校驗(yàn)。是否返回密碼、Token 等敏感字段。是否把詳細(xì)服務(wù)器錯(cuò)誤返回給用戶(hù)。是否將密鑰寫(xiě)死在源代碼中。安全檢查應(yīng)該單獨(dú)進(jìn)行不要默認(rèn)“功能測(cè)試通過(guò)就安全”。六、讓 AI 幫你驗(yàn)證而不是只讓它生成可以使用下面這個(gè) Prompt請(qǐng)不要直接修改下面的代碼先幫我驗(yàn)證它是否符合需求。 需求 [粘貼完整需求和業(yè)務(wù)規(guī)則] 代碼 [粘貼代碼] 請(qǐng)按照以下順序輸出 1. 代碼當(dāng)前實(shí)現(xiàn)了什么 2. 代碼做了哪些未經(jīng)確認(rèn)的假設(shè) 3. 與需求不一致的地方 4. 需要測(cè)試的正常、邊界和異常場(chǎng)景 5. 可能的安全風(fēng)險(xiǎn) 6. 仍然無(wú)法確定的問(wèn)題 請(qǐng)為每個(gè)問(wèn)題標(biāo)注高、中或低優(yōu)先級(jí)。 只有在我確認(rèn)問(wèn)題后再給出修改方案。七、不要只看 AI 的解釋AI 解釋代碼時(shí)可能非常流暢但流暢不等于準(zhǔn)確。驗(yàn)證答案時(shí)建議結(jié)合以下方式運(yùn)行最小示例。查看項(xiàng)目類(lèi)型定義。閱讀依賴(lài)庫(kù)官方文檔。搜索項(xiàng)目中已有的同類(lèi)寫(xiě)法。添加正常、邊界和異常測(cè)試。使用代碼審查工具檢查修改范圍。涉及核心邏輯時(shí)讓同事進(jìn)行人工評(píng)審。對(duì)于金額、權(quán)限、支付、數(shù)據(jù)刪除和隱私相關(guān)代碼驗(yàn)證標(biāo)準(zhǔn)應(yīng)該更嚴(yán)格。八、AI 生成代碼驗(yàn)收清單提交代碼前可以使用下面這份清單我能用自己的話(huà)解釋這段代碼。參數(shù)類(lèi)型、單位和取值范圍已經(jīng)確認(rèn)。正常輸入已經(jīng)測(cè)試。邊界輸入已經(jīng)測(cè)試。異常輸入已經(jīng)測(cè)試。依賴(lài)和 API 與當(dāng)前項(xiàng)目版本一致。返回結(jié)果符合接口約定。沒(méi)有遺漏權(quán)限和安全校驗(yàn)。沒(méi)有把示例代碼中的假數(shù)據(jù)帶進(jìn)生產(chǎn)環(huán)境。已經(jīng)運(yùn)行項(xiàng)目現(xiàn)有測(cè)試。已經(jīng)檢查本次修改的文件范圍。我知道這段代碼為什么這樣實(shí)現(xiàn)而不是只知道它能運(yùn)行。如果最后一項(xiàng)無(wú)法確認(rèn)說(shuō)明這段代碼還不適合直接提交。總結(jié)AI 生成的代碼之所以會(huì)“看著對(duì)其實(shí)錯(cuò)”常見(jiàn)原因有業(yè)務(wù)上下文不足。參數(shù)和字段含義存在歧義。使用了過(guò)時(shí)或不存在的 API。忽略邊界條件和異常處理。把示例代碼直接當(dāng)成生產(chǎn)代碼。使用 AI 編程時(shí)不要只問(wèn)“代碼能不能運(yùn)行”還要繼續(xù)確認(rèn)它是否符合需求是否覆蓋邊界是否適合當(dāng)前項(xiàng)目是否安全可以記住一套簡(jiǎn)單流程先讀需求 ↓ 確認(rèn)假設(shè) ↓ 運(yùn)行最小示例 ↓ 測(cè)試邊界和異常 ↓ 檢查項(xiàng)目環(huán)境與安全 ↓ 再提交代碼AI 負(fù)責(zé)提高編碼速度開(kāi)發(fā)者負(fù)責(zé)驗(yàn)證結(jié)果是否真實(shí)可靠。下一篇文章將介紹《從零搭建你的 AI 編程工作流》?堅(jiān)持原創(chuàng)求關(guān)注點(diǎn)贊收藏