像人類維護一樣寫程式碼 —— AI 生成重複內容的風險
像人類維護一樣寫程式碼 —— AI 生成重複內容的風險
太長不看版 (TL;DR)
使用 LLM 生成程式碼時,若不強制執行 DRY 或其他最佳實踐模式,會產生重複的條件判斷,這些判斷會成為儲存庫的新「風格」;接著模型會複製這些模式,使未來的維護變得更加困難。透過加入明確的審查指令、提示詞 (prompts) 和靜態分析,可以保持程式碼庫的整潔。
作者所描述的問題
作者描述了一種工作流程:反覆要求 LLM 在不同地方(路由處理程序、背景作業、API 端點、webhook)加入相同的存取檢查邏輯。每個生成的程式碼片段看起來都像這樣:
if (user.isActive && user.hasPermission('read') &&
!user.isSuspended && account.status === 'open') {
// do a thing
}
作者並沒有提取出共用的輔助函式,而是直接將每個副本合併進去,因為程式碼可以運作且測試也通過了。這種短期便利掩蓋了長期風險:每當有新的類似端點請求時,都會收到另一份相同的條件判斷副本,進而強化了重複的模式。當之後要求進行重構時,LLM 只會保留所有五份副本,因為那現在就是儲存庫的樣子。
關鍵要點: 每個併入程式碼庫的捷徑都會成為模型學習重複的訊號,將一次性的程式碼異味 (smell) 轉變為普遍的風格。
為何 LLM 會放大不良模式
- 上下文驅動生成 – LLM 會讀取你開啟的檔案和最近的提交 (commits)。它們將現有的程式碼視為未來建議的模板。
- 模式強化 – 重複的程式碼片段越多,模型複製它們的偏好就越強。
- 缺乏內在的可維護性概念 – 模型優化的是「根據提示詞產生的可用程式碼」,而非長期的可讀性或抽象化。
"LLMs are sponges that soak up everything you do and repeat it back to you. So make sure it's good." – Original post
社群建議的緩解措施
1. 加入帶有檢查清單的審查指令
- 建立一個 markdown 檔案(例如
.claude/commands/review.md)。 - 列出具體的檢查項目,例如「確保新程式碼不會重複現有的邏輯」。
- 在合併之前執行該指令 (
/review);代理程式 (agent) 將會生成計畫並標記違規項。
"Agents don’t care that they just got a wall of generic feedback, they happily look into all the bullet points. I added ‘ensure the new things aren’t duplicating code that already exists elsewhere’ and it gave me such a surprise – it really truly started planning cleanups!" – cadamsdotcom
2. 提示模型進行最終的程式碼品質檢查
在進行較大的變更後,要求模型驗證:
- 關注點分離 (Separation of concerns)
- 是否有殘留的實驗性程式碼
- 與文件的一致性
"Now do a final code check. Is everything tidy and do the components adhere to the principle of separations‑of‑concern?" – planb
3. 使用靜態分析作為基準
將 linter 或程式碼異味偵測器(例如 Credo, Rubocop, ESLint)整合到 CI 流水線中。接著可以要求 LLM 修復報告的特定問題,從而提供一個確定的安全網。
"Better yet, add tooling like static code analyzers … Verify against a mechanical baseline, with LLM judgement layered on top as‑needed." – chickensong
4. 定期進行基於模型的異味偵測
有些開發者會定期透過另一個 LLM(或專用的異味偵測模型)來掃描程式碼庫,以發現重複的模式。
"I continually run codebases through different models to have them look for bad code smells like repeated code. That’s been pretty effective." – carimura
反對意見與細微觀點
LLM 可以改善可維護性 – 有一位評論者指出,AI 有助於將其程式碼推向更好的關注點分離和可測試性。
"AI has made my code more human‑maintainable. They’ve been complaining about obsolete comments, separation of concerns, testability…" – andai
並非所有重複都是壞事 – 在專案的早期階段,過早的抽象化可能會造成傷害。在模式穩定下來之前,重複可能是可以接受的。
"When you start a project not everything is DRY, and you don’t start pulling out shared helpers until they’re called for."" – chickensong
LLM 可能會忽略現有的抽象化 – 有些使用者觀察到,即使在已經存在乾淨的抽象化時,模型往往會重新實作邏輯。
"The frontier LLM does neither, it just steams ahead re‑implementing things from scratch…" – davnicwil
人為的紀律- 仍是關鍵 – 依賴一個工程師團隊來持續應用審查提示詞 (prompts) 是很樂觀的;許多人擔心集體的紀律會逐漸侵蝕。
"The idea that an LLM‑fueled group will collectively have this discipline is… bemusing and saddening." – MattyRad
AI 輔助開發的實務檢查清單
- 定義一個審查檢查清單(重複偵測、DRY、命名慣例)。將其儲存在代理程式 (agent) 可以讀取的地方。
- 在每次合併之前執行
/review;將輸出結果視為強制性的程式碼審查項目。 - 加入靜態分析步驟 到 CI;若發現新的程式碼異味 (smells),則讓建置失敗。
- 定期安排 LLM 異味掃描 以捕捉趨勢漂移。
- 在加入類似邏輯時,明確提示模型進行抽象化:
- "Create a shared helper
hasReadAccess(user, account)and use it in all new endpoints."
- "Create a shared helper
- 在程式碼中記錄意圖,以便模型能看到其背後的原理,而不僅僅是實作作法。
結論
LLM 在快速產出可用程式碼方面表現出色,但若沒有嚴格的檢查,它們會鞏固重複且難以維護的模式。透過將模型視為一名需要明確指導的隊友——使用審查指令、品質品質提示詞和靜態分析——你可以保持程式碼庫的整潔,並防止 AI 學習不良的習慣。