iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Claude AI

資深工程師的 Claude Code 工作筆記系列 第 5 篇

Day 5:一件大工作,怎麼拆給好幾個角色分頭做

  • 分享至 

  • xImage
  •  

先老實說一句,今天這篇跳得有點大,希望不會太突兀。前四篇一路講小功能、講判斷方式,今天要直接跳去講 code review 這種比較重的東西,怕大家覺得跳太快。但這其實不是憑空冒出來的題目,Day 4 結尾就埋了這條線,一件比較大的工作,怎麼拆給好幾個角色分頭去做,code review 剛好是我自己想得到最適合拿來講這件事的場景,因為它是資深工程師每天都會碰到、又最容易讓人一個人做到崩潰的事。

我自己會挑這個場景,也是因為這件事我自己前陣子剛好認真想過一輪,不是今天為了寫文章臨時想出來的東西,是已經在用、也真的驗過一輪的做法,直接拿出來講,比臨時套一個場景誠實很多。

為什麼讓 AI 幫忙看 code,會停不下來

我自己一開始讓 AI 幫忙做 code review,遇到一個很煩的狀況,修完一輪它挑出來的問題,重新跑一次,又冒出新的東西,改完再跑又有新的,好像永遠沒有真的做完的一天。後來想通一件事,繼續找問題這件事,本來就沒有自然停下來的那個點。只要你一直問「還有沒有問題」,答案幾乎永遠是有,因為程式碼可以一直被挑剔,風格可以再調,命名可以再想,這件事沒有一個自然的零。

問題不是 AI 太雞婆,是我自己一開始的問法就錯了,我在問一個沒有終點的問題,當然永遠得不到終點的答案。

這種情況特別容易發生在一個人自己盯著整個流程跑的時候,一個人做事沒有下班時間會逼你停下來這種外在限制,團隊裡如果有好幾個人,通常會有人在某個時間點說一句差不多了,先上線再說,剩下的下次再處理。一個人自己跑的時候,沒有另一個聲音跳出來喊停,很容易就順著那個「還可以更好」的念頭一直繞下去,繞到後來才發現已經花了不成比例的時間在一個早就該收尾的地方。

這件事一開始很容易被誤會成工具不夠聰明,或者模型不夠強,換一個更厲害的模型應該就會知道什麼時候該停。我自己試過換模型,結果沒有改善多少,因為問題根本不在模型的能力,在於整件事的框架。只要框架本身沒有終點,不管換多聰明的模型去跑,都只是跑得更用力地在一個沒有底的坑裡繼續挖,不會因為挖得更用力就挖到底。

拆成三個角色,才有辦法停下來

後來我把整個流程拆成三個角色,各自負責不同的事,中間不共用同一個上下文。

第一個角色負責找候選,用一個完全乾淨、沒看過前面修改過程的視角去看程式碼,找出所有看起來可疑的地方。這個角色的工作很單純,找,不判斷,找到的東西不代表一定是問題,只是候選。

第二個角色負責判斷這些候選裡,哪些真的擋得住,哪些是雞毛蒜皮。這個角色要做的事是拿證據,去把每個候選項目實際驗過一次,是不是真的會壞、壞了會有多嚴重,不能只憑感覺說這個看起來有點怪。沒有證據支持的候選,直接淘汰,不會因為講得好像很有道理就留著。

第三個角色只負責收尾,確認前面篩出來、真的算數的問題,有沒有真的被修好,修完之後有沒有引入新的問題。這個角色不找新東西,純粹核對。

這三個角色為什麼要分開,不能讓同一個角色從頭做到尾,關鍵在第一個角色一定要保持乾淨。如果找候選的人同時也是改過程式碼的人,他腦子裡會帶著一整套「我剛剛已經處理過這裡」的假設,看東西的時候自然會避開自己已經動過的地方,真正的問題常常就藏在那個死角裡。這跟前面幾天講的寫的人不能驗自己寫的東西是同一個道理,只是這裡不是驗證一份文件,是驗證一段程式碼,換人這件事一樣重要,甚至更重要,因為程式碼壞掉的代價通常比一篇文章寫錯更高。

實際做的時候,我會讓找候選的角色完全不知道前面修改的過程,直接對著目前這個版本的程式碼去看,像是第一次見到這份東西一樣。判斷能不能擋的角色,我會要求它拿出具體證據,不能只憑印象講,像是真的跑一次會不會壞、能不能重現問題,講不出具體證據的候選,一律先放進待觀察,不算數。收尾的角色最單純,只確認該修的地方修了沒有,沒有修完不能收,修完但引入新問題也不能收。

這三個角色分開之後,完成的定義就從「AI 沒有話講了」變成「已經沒有新的、驗證過真的會擋事的問題」。前者永遠不會發生,因為找碴這件事沒有底,後者是一個真正可以達到的狀態,因為驗證過的問題數量是有限的,篩到零就是零,不會無中生有。

完成的判準要換掉,不是找不到東西,是沒有驗證過的阻礙

這個轉變我自己覺得是整件事裡最關鍵的一步。以前我會用「還有沒有發現新東西」當作要不要繼續的標準,這個標準永遠會告訴你「還有」,因為找碴這件事沒有自然的終點。換成「還有沒有驗證過、真的會出事的阻礙」之後,這個標準是會歸零的,因為能被驗證擋住的問題數量有限,篩完就是篩完了。

這件事聽起來只是換個問法,但實際做起來差很多。舊的問法會讓人一直陷在「還可以更好」的迴圈裡,永遠覺得沒做完。新的問法讓你清楚知道,今天這一輪,真正擋事的問題都處理完了,剩下的都是意見或偏好,不是非改不可的東西,可以先放著,不用為了追求某種完美狀態一直繞下去。

我自己會把每一輪找出來的東西,先分成兩堆,一堆是真的會讓程式壞掉或行為不對的,一堆是單純看起來比較好看、比較習慣的寫法。只有前面那堆會被算進「有沒有驗證過的阻礙」,後面那堆我會記下來,但不會拿來當作這一輪還沒做完的理由。這個分法一開始做起來會不太習慣,因為看到一個明明可以寫得更漂亮的地方,會很想順手改掉,忍不住的時候也真的會手癢改一下,但如果每次看到可以更好的地方都要改,那就真的回到原本那個沒有底的坑裡了。

哪些步驟該交給固定規則跑,哪些才需要真的判斷

除了拆角色,另一件我自己覺得很重要的事,是搞清楚 code review 這整件事裡,哪些部分其實不需要判斷,用固定規則跑就好,哪些部分才真的需要有腦子的東西去想。

我自己實測過一個叫 Open Code Review 的工具,版本是 1.12.1,跑在一個我自己刻意放進兩個 bug、再混一個正常改動的小 repo 裡,拿它跟一般直接丟給模型自己決定怎麼看的方式做對照。它把要看哪些檔案、套用什麼規則、覆蓋率夠不夠、留言要貼在哪個位置,全部做成一條看得見的流程,這幾件事本來就是機械性的事,範圍怎麼界定、規則要不要套用、覆蓋率算出來是多少,這些都有明確答案,不需要浪費判斷力在這上面。真正該留給有判斷力的角色去想的,是看到一段程式碼之後,這裡到底會不會出事,這種需要理解上下文、理解意圖的事,機械規則做不到,硬要寫成規則,只會變成一堆例外堆疊出來的怪東西,越補越亂。

同一輪測試裡,通用的審查方式跟這個做成固定流程的工具,抓到的 bug數量一樣,也都沒有抓錯東西,但固定流程那邊反而跑得更快,用的資源更少,因為它把不需要判斷的部分先擋掉了,省下來的資源可以留給真正需要想的地方。這個發現我自己覺得比想像中重要,不是工具比較神,是分工分對了地方,效率自然會提升。

具體一點講,範圍要看哪些檔案、要套用哪一條規則、覆蓋率算出來過不過門檻、留言要貼在程式碼的哪一行,這幾件事都有明確答案,寫成固定規則去跑,結果每次都一樣,不需要每次重新想一遍,也不會因為今天心情或狀態不同,跑出不一樣的結果,這種穩定性正是機械規則的價值所在。真正該留給有判斷力的角色去想的,是看到一段改動之後,這裡的邏輯合不合理、這個決定會不會在某個邊界情況壞掉、這樣寫是不是真的解決了原本要解決的問題,這幾件事沒有標準答案,得靠理解上下文才能判斷,交給固定規則只會得到看起來很像樣但其實抓不到重點的結果。

分不清楚這兩層,最常見的後果是把該用判斷力的事,簡化成一套規則硬套,或者把該用規則跑的事,每次都重新丟給大模型想一遍,前者會漏掉真正該注意的問題,後者則是在浪費資源做不需要判斷的事。我自己剛開始做這件事的時候,兩種錯誤都犯過,一開始想省事,把該仔細想的地方也交給一套死規則去卡,結果放過了明顯的問題,後來又矯枉過正,什麼都丟給模型重新想一遍,結果光是等結果就花掉不少時間,後來才慢慢抓到這條界線該畫在哪裡。

三個角色,不用同一個等級的模型做

前幾天講過,我不會每件事都丟給最聰明的模型做。這個習慣套到今天講的三個角色上,也一樣適用。找候選這個角色,工作性質比較像是廣撒網,用中等等級的模型正常仔細找就好,這個階段寧可多抓一些看起來可疑的東西,也不要漏掉,反正後面還有一關會篩掉不算數的。判斷能不能擋這個角色,才是真正花錢的地方,這裡需要的是拿證據去驗證一個候選到底站不站得住腳,判斷錯了會讓真正的問題被放過,或者把不是問題的東西當成問題去改,浪費時間,這個角色我會用最強的等級。收尾核對的角色,工作內容比較單純,確認修完了沒有,中等等級就夠。

這樣分配下來,整體花的資源不會比全部都用最強模型跑一輪高多少,因為真正吃資源的判斷步驟只有一關,前後兩關都可以用比較省的方式處理,但整體品質不會因此打折,因為真正需要判斷力的地方,該花的還是花了。這個分法也適用在人力有限、只有自己一個人的情況,就算沒有真的動用不同等級的模型,光是在心裡把三個角色的工作性質分清楚,知道哪一段該花力氣仔細想、哪一段掃過去就好,也能省下不少不必要的力氣。

自己內部做過的一次對照實驗

前陣子我自己也做過一次小規模的對照測試,想確認官方那個內建的審查功能,到底差在哪裡。找了兩個自己寫死答案的程式片段,一個裡面真的藏了一個 bug,一個程式碼是對的但可以簡化,各自跑一輪有用跟沒用這個功能的版本。先寫死答案這一步我自己覺得很關鍵,如果不先知道正確答案是什麼,事後看兩組結果,很容易變成公說公有理,這次先把答案釘死,才有辦法客觀比對誰抓到了、誰沒抓到,而不是憑印象覺得哪一組講得比較有道理。

第一個案例,一個計算折扣的函式忘記除以一百,導致算出來的數字是負的一大串,明顯是錯的。兩組不管有沒有用這個審查功能,都抓到了同一個 bug,也給了同樣方向的修法建議。差別在講法,沒用的那組是一段話夾雜著講,用了的那組拆成兩條各自獨立、標明清楚哪裡會壞的發現。

第二個案例反過來,一段正確但寫得比較囉唆的加總邏輯,沒用審查功能的那組反而更犀利,直接寫出一行就能取代的簡潔寫法,用了審查功能的那組只講了一句「這裡邏輯冗餘」,沒有給出具體能換成什麼。不過用了審查功能的那組多抓到一個型別不一致的問題,把一個看起來只是風格建議的地方,正式列成一條獨立的發現,沒用的那組只當成風格建議帶過。這個反轉一開始讓我有點意外,本來以為專門的審查功能應該每一項都表現得更好,結果在給出具體替代寫法這件事上,反而是沒有特別工具介入的那組表現得更好,這也提醒我不要預設某個功能一定全面勝出,實際測過才知道差異出現在哪裡。

這兩個案例合起來看,比單獨看任何一個都有意思,因為它們指向不同方向,如果只做案例一,會得出「這個功能很準」的印象,如果只做案例二,又會得出「這個功能不如自己看」的印象,兩個都做才看得出真正的差異藏在哪裡。我自己看完這個結果,最站得住腳的結論不是「這個功能有沒有用」,樣本數只有兩個案例各一輪,講不出這麼武斷的話。真正看得出來的差異,是有沒有用這個功能,抓到的問題其實差不多,差別在輸出的紀律,會不會把每個發現拆成獨立、可以個別核對的單位,還有會不會把容易被輕輕帶過的小問題,正式列成一條該處理的項目。這個發現剛好呼應前幾天講的另一件事,回報要有固定格式,這裡也是同一個道理,內容差不多的時候,有沒有紀律去呈現,決定了後面的人要不要花額外的時間自己整理一遍。

老實說這個實驗規模小到我自己都不敢拿去說服別人什麼,兩個案例、各跑一輪,換一批案例結果可能完全不一樣,我把它放在這裡不是要證明什麼結論,是想老實記錄一件事,就算樣本小,只要方法設計得乾淨,像是先寫死答案再去對照,還是可以看出一些值得繼續追的方向,只是不能把這種小規模觀察,講得好像已經是定論。這系列的其中一個原則就是不預告沒驗過的效果,這裡也一樣,看到的就是看到的,沒看到更大規模驗證之前,不會講得更滿。

交出去的東西,也要讓人看得懂在講什麼

還有一塊我自己覺得常被忽略,AI 幫忙產出一大包改動之後,人要怎麼看得懂、驗得完,這件事跟前面拆角色審查是兩件互補的事,一個是怎麼找問題,一個是怎麼讓交出去的東西容易被檢查。這兩件事常常被混在一起講,好像只要審查夠仔細,交付方式怎樣都無所謂,但我自己的經驗是,就算審查做得再徹底,交出來的東西一團亂,後面要花的力氣一樣省不掉。

這件事不只是我自己在意,前陣子看到有人在網路上公開問過類似的問題,怎麼讓 AI 寫的 PR 更容易被人 review,讓準備合併的改動更容易被檢查,這代表這不是我自己遇到的特殊狀況,是很多人一起卡住的地方。我自己現在的習慣是,交出去的東西一定要附一份說明,為什麼要改這個、行為上差在哪裡、還有哪些地方沒驗過,不然對方拿到的只是一堆改動過的檔名,還是得自己重新拼湊一次到底發生了什麼事,等於白做工。看的順序我自己也會盡量固定下來,先看前後行為差在哪,再去對應到程式碼的哪個位置,最後核對有沒有測試證據撐著,不會東翻西翻,看到哪算到哪。

這份說明我自己會準備成一個固定的交接格式,甚至可以直接貼給 AI 用,讓它照著這個格式把自己剛剛做的改動講清楚,而不是每次都用自己的方式亂描述一通。格式固定下來之後,不管今天是哪個角色、哪一輪產出的東西,看的人都知道要去哪裡找答案,不用每次重新適應一套新的敘述方式,這件事跟前面講的回報要有固定格式,其實是同一個道理再用到另一個地方。

換角色要換得徹底,不然等於沒換

有一個細節我自己踩過,如果三個角色只是形式上分成三個步驟,但其實是同一段對話接著往下跑,前面的假設還是會滲透過去,換角色這件事就白做了。找候選的角色如果知道前面已經改過哪裡,多少會被那個資訊影響判斷,看東西的時候不自覺就會避開已經處理過的地方,跟完全不知道前情的狀態下去看,結果不一樣。

所以我自己現在會刻意讓找候選這一步,是真正全新的一輪,不帶著前面的對話記憶,逼自己重新從頭看一次現在這個版本的程式碼,像是第一次打開這份檔案一樣,不去想之前討論過什麼。這樣做確實比較麻煩,要多交代一次背景,但少了這一步,前面講的三個角色分工,很容易變成表面上換了名稱,實際上還是同一套假設在跑三遍,沒有真正解決問題。

判斷能不能擋的那個角色也一樣,我不會讓它直接沿用找候選那個角色講的話當成事實,就算對方講得再篤定、再有條理、附上再具體的位置,也要重新拿證據驗一次,附了位置不代表那個位置真的會被這次的情況觸發到。這件事聽起來有點麻煩,好像在互相不信任,但這正是這整套方法能成立的原因,每一關都不預設前一關一定是對的,才不會有一個小小的錯誤,一路被放行到最後,變成最後才發現的大問題。

不是每次改動都要這樣搞

講了這麼多,也該老實補一句,不是每一次改動都需要把三個角色全部搬出來跑一輪。改一行文字、調一個顯示用的數字,這種影響範圍很小、錯了也很好發現、改錯了也很好收回的改動,我自己不會特地拆成三段,那樣反而是把簡單的事情弄複雜,多花的時間比省下來的風險還高。

真正值得搬出這一整套的,是那種影響範圍不小、錯了不容易馬上發現、改錯了代價很高、或者要改的地方牽涉到好幾個檔案互相影響的改動。這種時候,光靠自己盯著看一遍,很容易因為改的時候腦子裡那套假設,把真正的問題看漏,這時候拆成三個角色分頭把關,才划算。判斷要不要拆,我自己是看這次改動如果出錯,會不會很晚才被發現,或者發現了要花很久才能追回問題根源,如果答案是會,那就值得拆,如果答案是不會,直接自己看一遍改一改就好,不用每次都搬出整套流程。

這套方法也有破得掉的地方

寫到這裡,也該老實講清楚這套方法的限制,不能講得好像照這樣做就萬無一失,那樣反而違背這系列一開始講的誠實原則。三個角色分頭把關,防得住的是執行過程中的疏漏,防不住一開始的方向就選錯。如果一開始要做的這件事,理解錯了,或者需求本身就搞錯方向,三個角色檢查的都是同一個錯誤的目標,各自看起來都做得很仔細、很認真,合起來還是在驗證一件不該做的事。這種問題不是靠拆角色能解決的,得回到更前面,先確認要做的這件事本身有沒有問題,這也是為什麼這系列一直強調,判斷該不該做這件事,我自己還是會親自把關,不會全部交出去,這條線我很清楚不會鬆動。

另一個限制是,如果三個角色用的是同一個模型家族,就算真的用了完全乾淨的新對話,還是可能帶著同一種思維習慣,遇到同一類的東西都容易忽略,這種情況光看單一輪的結果很難察覺,得累積好幾次觀察,才會發現某一類問題怎麼樣都逃過所有角色的眼睛。這種共同的盲點,換再多次對話也換不掉,真正要補這個洞,得靠不同來源的檢查,像是真的跑起來看行為、或者換一個完全不同的模型去看,而不是只在同一種工具裡面換角色的名字。

我自己現在對這件事的態度是,拆角色能解決的是「同一個人帶著同一套假設從頭做到尾」這個問題,解決不了「一開始的方向就選錯」或者「用的工具本身有共同盲點」這兩種更深的問題,這兩層問題性質不一樣,不能指望同一套解法一次全部搞定。前者要靠自己在動手之前多想一層,後者要靠偶爾引入完全不同的檢查方式,兩者都不是靠把流程拆得更細就能自動解決的,這條界線我自己會分清楚,不會誤以為流程夠細就等於萬無一失。

這件事跟一個人跑完整條線的關係

回到這系列最一開始講的那個野心,一個人要跑完整條開發線,code review 是我自己覺得最需要補位的一段。以前這關是團隊裡另一個人幫你把關,現在只剩自己一個人,原本那個人的角色沒有消失,是我自己要把它重新蓋回流程裡。

今天講的這幾件事,拆成三個角色分頭做、換掉完成的判準、分清楚哪些交給固定規則哪些交給判斷、還有交出去的東西要讓人看得懂,湊起來剛好就是一個人怎麼把原本要靠團隊互相補位的那道關卡,自己一個人重新撐起來。少了任何一塊,這道關卡都會有漏洞,全部湊齊,才勉強撐得住一個人扛下這件事。

第二個角色,判斷候選能不能擋的那個,其實跟這系列第一天講的那條紅線是同一件事的兩種說法。那條紅線說的是不能為了把事情做完而編一個聽起來合理的細節,這裡的規則是不能因為一個候選講得很篤定就直接採信,兩句話合起來,其實就是同一個態度,沒有證據撐著的說法,不管講得多順、多有道理,都不能當真的。我自己覺得這個態度貫穿了這系列到目前為止講的每一件事,只是每天套用在不同的場景上而已。

寫到這裡回頭看,這系列從第一天講判斷方式,到今天把判斷方式具體套進 code review 這個場景,中間其實沒有換過核心的東西,換的只是場景跟細節。我自己覺得這才是這系列真正想留下的東西,不是一份工具清單,是同一套判斷方式,能不能套進不同的場景裡都還站得住腳。

如果只記得今天這篇的其中一件事,我會希望是這句話,完成不是等到沒有話可以挑了,是等到沒有驗證過、真的會出事的東西了。這句話換一個場景講也成立,不管是審程式碼、寫文章,還是做任何一件會讓人陷入「還可以更好」迴圈的事,這句話都是讓自己能夠停下來、而不是無限循環下去的那把鑰匙。明天想找一個新的場景,看看這句話套進去還站不站得住腳。

今天這篇算是把 Day 3 說的重量級工具跟多角色分工提前搬出來用了一次,順序跟原本排的不太一樣,但這系列一開始就說過,地圖會照實際遇到的場景調整,不會硬照原本排的順序走。

下面講下一個場景,會回到 Day 3 提過的需求定義那段,這個之前一直延後,這系列也差不多該回去補上了。


上一篇
Day 4:連這篇文章,都是跟 Claude Code 一起弄出來的
下一篇
Day 6:需求講得再順,都可能只是講得順而已
系列文
資深工程師的 Claude Code 工作筆記 共 11 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言