推特上流傳著一句話:「沒有任何人類能寫出比 LLM 更好的程式碼。接受這個事實,別再裝了,然後往前走吧。」
以下是我的回應。
這個問題裡對「更好」有很多隱含前提。LLM 的訓練目標是生成看起來合理的內容,而不是正確的內容。你可以讓它產生多優雅、多符合慣用寫法、多流暢的程式碼都行,但它還是可能忽略真正重要的限制條件(既有系統、團隊慣例、商業考量、失敗模式、尚未成真的功能)。
資深工程不只是「寫」程式碼而已,而是知道什麼時候不該寫。它在於辨識真實的邊界案例,以及那些還沒成熟的抽象化;知道某個問題其實可以用更簡單的方式解決,甚至根本不需要解決。這種判斷很難量化、很難靠提示詞引導,而且在生成的解答裡常常不明顯。
所以沒錯,LLM 可以是很好用的工具,但離真正的人類專家還差得遠。
那個推文裡最讓我在意的字就是「更好」。所以我把它的意思寫下來。
「更好」這個詞,我們常常把它當成一個純量值來看。換句話說,好像只有一個值能定義什麼叫更好。然而,當你問「更好」是在衡量什麼時,你會發現:是每分鐘寫幾行?是正確性?是可維護性?還是有沒有勇氣不把它做出來?你很快就會意識到,「更好」會依照你衡量的維度不同,而有完全不同的意思。
生產力指標是每分鐘寫幾行。這是一個很棒、很簡單,而且很容易衡量的指標。因為它看起來像是進步,所以這個指標很有吸引力。可是,它衡量的其實只是輸入文字的速度,並不代表最後的程式就比較好。
一千行錯誤的程式碼,比完全不寫還糟。一千行一看就會崩掉的程式碼,比那還更糟。所以,接著我們會看正確性。我們希望程式碼更好,因為它是正確的。它有正確的功能,也符合規格,並且能通過測試。這算是一種進步。但還不夠。
真正的噩夢是:LLM 生成的程式碼在出問題之前都能正常運作,但它出問題時,你根本看不懂。你會拿到一段看起來很合理的程式碼,它不知怎地就進了正式環境;然後你的金流管線突然開始默默丟棄交易,因為模型心血來潮在你的交易處理函式上加了一個 retry_on_timeout 裝飾器,這個裝飾器會攔截例外、記錄一條 WARNING,然後回傳 None。後面的程式把這個 None 當成零元成功扣款來處理,於是你的客戶就開始免費拿到他們訂購的商品了。
Gramli 在〈To Retry or Not to Retry〉(https://dev.to/gramli/to-retry-or-not-to-retry-that-is-the-question-1j2l) 裡測試過類似的情況。在某個情境中,一個付款請求回傳了 503,並帶有 Retry-After 標頭,但沒有冪等金鑰。8 個模型裡有 6 個都照著標頭內容建議重試,只有 2 個說不要。
Dex from HumanLayer 在他的演講〈Harness Engineering Is Not Enough and Why Software Factories Fail〉裡解釋了為什麼會這樣。許多程式碼基準測試只給模型通過或失敗的獎勵。當測試通過時,模型就算贏了,而不良設計並不會受到任何懲罰。所以它學會了加上 try/catch 或型別轉換,因為這些做法能讓測試通過。
我們可以擁有一段非常好的軟體,但它卻無法再改動。這正好和我們想要的相反。這就是遺留程式碼,而且它很糟。我們需要能夠不痛苦地修改它。
所以我們會透過讓它具備可維護性來改善它。可維護的程式碼是可讀、簡單的程式碼,是那種不會讓任何人想把辦公室燒掉的程式碼。它不會隨著時間推移而壞掉。可維護的軟體就是能正常運作,能在不破壞現有功能的情況下滿足新需求與變更。
最後一種選項是最好的。這是智慧的衡量標準,是那種讓我們能說「不,我們不該做那個」的「更好」。它之所以更好,是因為它做得更少,但卻是必要的。
換句話說,程式碼是一種負擔,是我們應該盡量維持在最低限度的東西。這種「更好」是最難實踐的。它要求你對壓力、對預算、對那位覺得自己有個絕佳點子的利害關係人說不。這是一種少即是多的衡量方式。不過,因為沒有把某些東西做出來而累積的複利,會持續成長。
所以,「更好」不是單一件事。它是多件事。它是一個層級結構,而且會隨著我們經驗的累積而改變。我們會從每分鐘寫幾行,走向正確性,再到可維護性,最後到不去做。
原文出處:https://dev.to/dannwaneri/no-human-will-ever-write-code-better-than-llms-better-at-what-1dme