蒼時弦也
蒼時弦也
資深軟體工程師
發表於

身為工程師,我在 2025 年如何用 AI 寫程式

AI(人工智慧)領域的發展非常快速,在二月之前我還不覺得以 AI 來寫程式是有效的,因為我需要複製程式碼到編輯器中,然而 My LLM codegen workflow atm 這篇文章改變了我的看法,因為有一些工具已經足夠成熟能直接編輯檔案。

有非常多額外內容,我會把下半年連載的展示專案跟閒聊另外放在 YouTube 影片 裡面討論。

專業的界線

我認為我會在很長一段時間內不完全相信 AI 生成的程式碼,因為 LLM(大型語言模型)的基礎是建立在機率上的,也因此我們很難保證不會出錯,出於自身專業這是必須的。

然而,這並不代表無法控制生成的表現,我們有很多方法可以改善這樣的問題。如同 AI Coding Is Based on a Faulty Premise 這篇文章所提到的觀點,很多時候我們只是利用隨機性來產生可能需要的程式碼,但我們對實際需求一無所知。

近期熱門的 Vibe Coding(氛圍編程)對初學者或者有需要軟體幫忙解決問題的大眾確實是非常有用的工具,但是在專業領域的工作中,只會是手段之一(我認為適合用於 PoC)

我們以 Cloudflare 最近為 MCP 推出的 Workers OAuth Provider 的 README 描述舉例,這個段落特別強調使用 Claude 進行開發,但不是 Vibe Coding 的方式,而是經過工程師仔細檢查和確認的成果,用以保證軟體品質。

簡單來說,在專業軟體開發的情境,我們應該會有更嚴謹、安全的方式進行,而非 Vibe Coding 這種對品質、安全要求不高的做法。

Vibe Coding 對於降低軟體開發門檻是非常棒的方式,寫這篇文章前吳恩達呼籲全民擁抱用GenAI來寫程式,來大幅降低企業與個人的試錯和創新成本這篇新聞就很符合我的觀點,我也推薦朋友嘗試,以及在 Ruby Taiwan 跟高中電研社社團的合作課程採取這種方式。

規劃

最近讀書看到 10-80-10 法則 認為也非常適用在工作中與 AI 協作的情境,我們利用 10% 的時間規劃開發方式,再使用 80% 時間開發,最後用 10% 審核(Review)假設 80% 開發時間都交給 AI 處理,那麼最終我們只需要 20% 左右的時間。

在邏輯上比較合理,使用 AI 寫程式的文章通常都會建議用 Ask(提問)或者 Architect(架構師)模式,先跟 AI 討論規劃實踐的計劃,包括專案結構、元件組成、核心物件設計、風格等等都可以。

不過在這個層面,我認為仍會有「專業程度」的差異,以我目前的狀態為例,在工作中已經被認同擔任架構師,具備豐富的經驗和知識儲備,那麼非常多規劃、設計層面的問題幾乎不需要依靠 AI 就能處理,至少在這方面還是有優勢的。

然而,這也是另一個層面的挑戰。假設要讓這種能力規模化(Scale)到整個團隊,我需要的是另一種 AI 使用的方式,將知識和經驗轉換成知識庫(Knowledge Base)並且讓團隊能使用 AI 提取知識。

也因此,在這個階段會有數種不同的應用情境

  • 缺乏經驗,仰賴 AI 提供「可能正確」的建議
  • 基本經驗,仰賴 AI 提取缺少的知識
  • 豐富經驗,透過 AI 規模化知識到團隊

扣掉較資深的工程師是輸出的情境外,一般人跟工程師的差異只剩下判斷力,如何從整體只有 60% 正確率的回答中,分辨可行的方案。

正確率約 60% 是 2025 年三月份的新聞雖然會因為模型不同有所差異,像是 Claude 公認在回答程式問題正確率是相對高的,我也在團隊成員測試過(我的 Review Comment 成員用不同模型分析意圖,Claude 3.7 + Thinking 跟我的解釋最接近)

實作

實作是我們最希望 AI 來幫忙解決大量縮短時間的部分,然而以 60% 正確率來說,很多情境都沒有那麼理想,但確實能夠很好的幫我們加速。

可以參考 aider Leaderboard 的資訊,Claude 3.7 大概是 65% 左右,寫這篇文章時 Gemini 2.5 Pro 已經能達到 73% 左右,未來還是很值得期待。

如果是個人的興趣,或者產品的原型正確率 65% 已經非常夠用,畢竟在這種情況下出錯的成本、風險都不高,因此採用 Vibe Coding 就可以兼顧效率跟成果。然而在開發軟體服務時,如果有接近 40% 的功能都會出錯,大多數人都會覺得不合格。

幸好正確率這件事情並不代表每次都會產生有問題的功能,頂多只能表示大部分的功能都會存在不同嚴重程度的問題,因此需要人類去修復,或者透過「課金加速」用金錢的力量去解決。

「課金加速」是我跟朋友的玩笑,用於表示只要錢夠多可以無限用 AI 不斷嘗試除錯到正確為止,跟手遊抽到稀有卡一樣。

那麼,我們有什麼解決方案是用現在這個階段的情境呢?我的答案是進行「分級」的處理,區分出需要高度人工介入跟低度人工介入的程式碼。舉例來說,一個 API 欄位缺少無法使用,和一個金額計算會少算一條的嚴重性,後者嚴重非常多。

Clean Architecture、Domain-Driven Design 意外成為一個很不錯的方案,兩者的重點都不在於「怎麼做」而是「為何而做」的角度思考,因此我們可以依照這些思考基準先區分出「商業邏輯」跟「底層細節」兩大部分,前者以人類為主設計,後者則由 AI 依照商業邏輯定義的介面完成提供 HTTP API、整合資料庫等實踐。

這樣一來,整體表現就會相對穩定非常多,也能夠確保核心的行為是被保護的。在幾個不同小專案的實驗中,我認為商業邏輯實作約佔了 20% 左右的程式碼,這也算相當合理,因為這些商業邏輯大多是抽象、精確的描述。

現階段我會提議把這類程式碼看作是一種提示詞,而不是程式碼。要使用 AI 生成程式碼就需要提供脈絡,商業邏輯就是最佳的脈絡,而且這些商業邏輯正好是無法被大型語言模型訓練到的地方。

實作中需要針對 LLM 做非常多特殊處理才能得到穩定表現,進一步加速,但是篇幅會太長。我們先來看一下關於開發速度的議題比較一下。

在寫這篇文章前,我看了我的 WakaTime 紀錄,比較了現在正在連載的 Clean Architecture in Go 以及下半年預定的 Clean Architecture in TS 兩個系列的展示專案,後者有導入 AI 輔助開發。

  • Clean Architecture in Go 約 13.5 小時,cloc 排除 Markdown 約 3,300 行
  • Clean Architecture in TS 約 16.5 小時,cloc 排除 Markdown 約 4,500 行

現實總是殘酷的,使用 AI 後反而變慢了?

幸好這些誤差來自於實作的範例不同,直接比較不算非常公平。但是我們可以看兩個專案的差異,在 Go 版本中我使用了兩種以上的 Codegen 工具來處理,因此實作上有一大部分已經不太需要實際去寫。

假設我們把 AI Codegen 跟傳統的 Codegen 放在一起,可以看到兩者提供的加速是同一個級別的,但在情境上不同,因為 AI Codegen 提供了一種非標準方式的生成,如果是標準已經確定的情況,傳統的 Codegen 正確率會更好。

另一塊我們要看編輯檔案的時間比例,我在 Go 版本中除了核心的 Use Case(單一檔案)外,大部分時間都花在 Adapter Layer 的實作,也就是前面提到的底層細節實作,在整體的開發佔比中這類實作比例相對高上不少,但很多都是重複性的任務。

那麼 TS 版本的狀況又是如何呢?同樣的我在 Use Case 上花費的時間相對高,但是 Adapter Layer 的比例已經不是佔比最大的部分,我花費很多時間在處理某一個功能的測試,還有一份系統提示(System Prompt)的文件,其餘幾個檔案是我導入前人工寫的,但也被用於後續的參考基礎。

就結果來看,使用 AI 確實有可能加速,但是必須區分出哪些適合給 AI 寫,以及什麼階段給 AI 寫會比較好,至少專案初期設計給 AI 主導可能更浪費時間(之所以修測試,是因為我讓 AI 設計測試架構)

我們可以分幾個面向來看,第一種是 Clean Architecture 來區分應用程度

  • Entity - 推薦人工,搭配 AI 補全
  • Use Case - 推薦人工,搭配 AI 補,可混合 Agent
  • Adapter - 推薦 AI Agent,建議人工建置樣板
  • Framework & Driver - 主要使用函式庫,要考慮是否被訓練讓 AI Agent 能使用

另一塊則是開發階段的採用比例

  • 基礎架構 - 推薦人工、使用 Codegen
  • 前期開發 - 推薦 AI、建議人工建置樣板
  • 後期開發 - 推薦 AI、審查為主

從上述的情境來看,會發現有很多「樣板」的人工機制要處理,這些樣板可能會以程式碼、提示詞的型態呈現,但都對應到了「建立知識庫」的需求,當知識庫越完善那麼使用 AI 的效益才會越大、越順利。

雖然大部分模型都有經過「指示(Instruct)」的訓練,仍會有很多不遵守指示的狀況發生,我在使用 Copilot Agent 時就很容易遇到做太多反而破壞原有功能的狀況,這點能改善的話準確率也會很好的提升。

最後,因為 LLM 的訓練使用非常多書籍、網路資料,如果能熟悉像是 Design Pattern 這類術語,而且在正確的時機使用,那麼給予像是「在 service 目錄根據 setup-bank-account.md 文件實作一個 bank account builder」的提示時,也會比直接要求依照文件表現好。

到這一階段我的看法會是,在 AI 時代我們面臨最大的問題是人類本身攜帶的知識,怎麼最有效使用的問題。

審核

審核本身並不困難,因為有在做 Code Review 的團隊一定都有經驗,困難的地方在於我們大多對品質沒有明確的定義,也沒有標準。

因此,審核階段要做的事情並不是檢查 AI 寫程式碼好不好或者對不對,我們可以透過靜態分析(如:Linter)和動態分析(如:自動化測試)來處理大部分的情況,至少我們追求的不是那種完美排版沒有多餘內容的手工藝。

我們需要注重的是產出的程式碼是否具備優良的品質,這些品質的來源可能是架構類型的指標。如果我們不考慮耦合問題,讓 AI 產生一個單檔 1000 行的程式碼,把所有功能都放在裡面要通過動態、靜態分析都不是問題。

然而這樣的產出造成怎樣的問題?

下一次我要修改這個功能,需要反覆用 AI 生成 800 ~ 1200 行的成始碼,一直嘗試到能通過測試為止。這樣開發效率又退回到人類開發的時代,這並不是我們想要的結果。

所以品質本身來自於我們能不能很好的讓這些產生的程式碼具備良好的可維護性,這種可維護性不是人類可以維護,而是在現有軟體系統層面的可以維護,以此為出發點以往一些程式碼太長、不好閱讀這種類型的問題都可以被容忍。

程式碼太長仍會對 AI 造成影響,因為會有 Lost in Middle 這樣的現象,雖然目的不是要讓人類能輕鬆閱讀,但對於工具特性掌握,維持工具保持最佳效果還是很重要的一環。

我想未來會慢慢有類似的概念出現,幫助我們對於如何評估 AI 產出有更好的基準,甚至一定程度也會用 AI 來幫忙,我們只需要最很關鍵的檢查(如:是否安全)

至於用 AI 產生單檔 1000 行的情況是否會有,我最近處理信用卡公司帳單的腳本就長這樣,因為我需要的是把我每個月要花 60 分鐘打字記帳變成 1 秒,即使出錯或者要調整,只要做完這一次就省下非常大的時間成本,因此不管怎樣這樣做都是值得的。