iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
IT Operation

AI 時代下,如何建立真正可持續的軟體交付能力系列 第 20

Day 20. 預防性重構:建立生成後即整理的工程習慣

  • 分享至 

  • xImage
  •  

AI 生成結果為什麼只能視為候選變更

AI 生成完成,仍屬於待驗證的候選變更

AI 可以根據需求描述、現有程式與架構規範,快速產生修改內容。這些內容完成後,仍屬於「候選變更」,提供的是可評估的解法,還需要經過工程驗證,才能進入主幹或發布流程。

這樣的定位能幫助團隊建立清楚的責任界線。AI 協助產生程式與提出解法,開發者負責理解變更、檢查風險,並決定是否採用。

即使生成結果可以編譯,測試也已通過,團隊仍要看案例是否正確,修改是否碰到缺少保護的區域。

AI 產出的程式應該和人工撰寫的修改採用相同工程門檻。需求確認、架構檢查、程式碼審查、自動化測試與副作用分析,都要在合併前完成。

團隊先把生成內容視為草稿,再透過整理與驗證,讓它具備可維護的系統變更。

生成結果需要經過需求意圖確認

AI 接收到需求後,會依照提供的文字、範例與程式上下文推導實作方式。當需求中有模糊處、遺漏條件或未說明的業務規則時,AI 仍會嘗試補齊細節。產出的程式看起來完整,採用的假設仍可能偏離產品需要。

開發者需要先回到需求意圖,確認這次修改想解決的問題、預期改變的使用者行為,以及哪些情境不能受到影響。

例如需求寫著「訂單取消後退回庫存」,AI 高機率能產生庫存回補程式,也可能忽略部分出貨、預留庫存、重複取消與跨倉調撥等規則。

需求意圖的確認也包含失敗情境。正常路徑可以執行,只能說明其中一組案例通過。輸入資料不完整、外部服務逾時、交易只完成一半,或同一指令重複送出時,系統應該如何反應,都需要明確檢查。

這些確認適合透過驗收條件、行為範例與測試案例完成。開發者應能說明生成內容對應哪一條規則、處理哪些案例,以及哪些假設仍待確認。說不清楚時,這次修改就應先停下來。

架構規範需要被驗證到具體程式邊界

團隊建立分層架構、模組規則與依賴限制,可以有效縮小 AI 的生成範圍。

規範能告訴 AI 哪些元件負責業務邏輯、哪些元件處理資料存取,以及模組之間允許透過哪些方式溝通。文字規範能提供方向,落實程度仍要回到實際程式依賴與資料流檢查。

AI 可能把程式放在正確資料夾,類別名稱也符合團隊慣例,實際責任卻落在不適合的位置。

例如控制器(Controller)直接操作資料庫、領域物件呼叫外部服務,或應用服務同時處理交易、通知與資料轉換。表面結構符合規範,模組責任已經開始混合。

依賴方向也需要具體驗證。新增套件引用、共用工具或跨模組呼叫,都可能讓原本清楚的邊界產生新的耦合。

這類變更短期內可以正常運作,後續修改時才會顯示影響,例如測試需要建立更多相依物件,或單一業務規則必須跨越多個模組調整。

團隊可以透過架構測試、依賴分析與程式碼審查檢查這些問題。審查時需要沿著呼叫路徑與資料流確認責任分配,檔案位置與命名只能當成第一層線索。架構規範若能進入自動化檢查,人工判讀就不必每次從零開始。

團隊慣例需要透過審查與自動化檢查落實

程式碼裡常有許多沒有完整寫進架構文件的工作慣例,例如錯誤訊息格式、日誌欄位、交易處理方式、測試命名、資料驗證位置與 API 回應結構。這些慣例會影響系統一致性,也會影響開發者閱讀與除錯的方式。

AI 能從現有程式推導模式,若同一個程式庫存在多種寫法,AI 可能選到容易模仿的版本,和團隊目前希望採用的方式不一致。新程式通過基本測試後,錯誤處理、命名與結構仍可能出現另一種變體。

程式碼審查(Code Review)可以補足這些情境資訊。審查者需要確認生成內容是否延續團隊目前採用的設計方式,也要指出哪些局部寫法會讓後續維護產生混亂。這類回饋應該回到規範、範本或檢查工具中,避免每次都依靠審查者重新提醒。

能明確判斷的規則適合交給自動化,例如格式、靜態分析、安全掃描、依賴限制與測試門檻。需要理解業務背景與設計取捨的內容,則保留在人工審查。兩者搭配後,團隊才能在生成量提高時,維持一致的工程標準。

合併前要確認測試、行為與副作用

測試通過是候選變更進入合併流程的重要條件,測試結果仍要搭配案例內容一起解讀。

AI 可能同時產生程式與測試,兩者若共享同一個錯誤假設,測試仍然可以順利通過。開發者需要確認測試驗證的是需求行為,並且涵蓋關鍵邊界與失敗情境。

除了新增測試,既有測試也要完整執行。局部修改可能影響共用元件、事件處理、快取、資料格式與權限判斷,這些影響未必會出現在目前檔案附近。

整合測試、契約測試與端對端測試,可以協助團隊檢查跨模組行為是否維持一致。

副作用檢查則關注程式執行後改變了哪些狀態。例如新增資料庫寫入、發送訊息、呼叫外部 API、清除快取或更新搜尋索引,都需要確認失敗處理、重試與重複執行的結果。只檢查函式回傳值,容易漏掉這些系統層級影響。

合併前,開發者應能說明變更範圍、測試證據與已知風險。遇到難以回復的資料修改、高權限操作或關鍵交易流程,還需要補上回退方式與觀測資訊。

完成這些檢查後,AI 生成內容才能從候選解法,轉成團隊願意承擔的正式變更。

生成後即整理如何降低長期維護成本

趁上下文還清楚時整理設計意圖

AI 生成程式時,許多設計判斷來自提示詞、對話內容與開發者當下補充的背景。

這些資訊未必會完整保留在程式中。生成工作剛完成時,開發者仍能說明每個類別、方法與條件判斷對應的需求,也知道哪些地方是為了快速驗證而採用的暫時做法。

這時進行整理,可以把原本存在於對話中的意圖轉進程式結構。例如將模糊的函式名稱改成業務用語,把藏在條件判斷中的規則抽成具名方法,或將臨時參數改成清楚的設定物件。後續閱讀者不必回頭翻找整段 AI 對話,也能看出程式用途。

設計意圖也包含當時沒有採用其他方案的原因。若某個做法受到相容性、時程或外部系統限制,團隊可以透過註解、架構決策紀錄(Architecture Decision Records, ADR)或拉取請求(Pull Request, PR)說明留下背景。

這類資訊能協助後續開發者判斷限制是否仍然存在,也能避免 AI 在下一次修改時重走同一條錯路。

整理完成後,開發者應能離開原始對話,直接說明這段程式負責什麼、依賴哪些條件,以及哪些行為需要被保護。

趁變更範圍還小時修正命名與結構

剛生成完成的變更,多半集中在少數檔案與功能範圍內。此時調整名稱、拆分方法或移動責任,影響面較容易掌握。

開發者可以搭配新建立的測試確認行為,也能及早看出結構調整是否已超出原本需求。

命名不清楚時,後續維護者需要反覆閱讀實作,才能理解程式用途。像是 handleDataprocessResultcheckStatus 這類名稱,無法說明處理的是哪一種資料、結果與狀態。當相似名稱散布到多個模組,搜尋與除錯都會變得費力。

結構問題也會隨著後續功能加入而擴大。一個同時負責驗證、計算、資料存取與通知的方法,初期仍能被理解。等條件與分支繼續增加後,任何修改都需要檢查整段流程。生成後先將責任分開,可以讓每個區塊對應較明確的修改原因。

小範圍整理還能降低修改阻力。當每次變更都順手處理附近的新問題,程式可讀性就不必另外排成大型專案。

若所有調整都等待大型重構,工作範圍會擴大,測試需求與協調成本也會提高,最後很可能再次被交付壓力延後。

讓審查聚焦在可理解的小批次

程式碼審查(Code Review)需要理解需求、程式行為與風險。AI 一次產生大量修改時,審查者容易把注意力花在追查程式做了什麼,留給設計判斷的心力就會減少。

生成後先整理,可以縮小不必要的差異,讓審查者少花時間辨識雜訊。

小批次代表每次拉取請求都聚焦在一個清楚目的,程式結構也已經完成基本整理。審查者可以沿著需求、測試與實作逐一確認,不需要同時處理大量改名、搬移、格式修正與功能新增。

整理也能讓審查意見集中在模組責任、錯誤處理與資料一致性。格式、語法與可自動判斷的規則,可以在送出審查前由工具處理。

可理解的小批次也較容易回退。若上線後出現問題,團隊能從單一變更確認影響範圍,並快速決定修正或撤回。當功能修改與大量結構變動混在同一批提交中,問題定位會被拉長。

避免臨時取捨變成後續預設做法

開發過程中常會出現臨時取捨,例如先寫固定值、暫時跳過某個驗證、直接呼叫特定服務,或為了趕上驗證時間而複製一段邏輯。這些做法在限定範圍內可以協助團隊快速取得結果,仍需要在進入正式流程前重新檢查。

AI 容易延續程式庫中已存在的模式。若臨時寫法被合併到主幹,後續生成時便可能被當成參考範例,再出現在其他模組。原先只存在一個位置的取捨,會透過多次生成形成團隊難以統一處理的慣例。

生成後整理需要辨識哪些內容屬於正式設計,哪些屬於探索過程留下的痕跡。能立即修正的部分,應在合併前處理。受到時程或外部條件限制的部分,則要建立可追蹤任務,記錄影響、處理條件與預計回頭的時機。

這種做法可以避免臨時決定失去背景。後續團隊看見某段簡化實作時,能知道它存在的原因與限制,也能判斷何時需要調整。

乾淨、規範統一的程式庫,能做為 AI 下一次提示詞或檢索增強生成(Retrieval-Augmented Generation, RAG)的優質範例。未即時整理的壞程式碼,則可能被下一次生成繼續引用。

如何用命名、抽取與結構調整改善可讀性

生成後整理,先從局部可讀性開始

AI 產生的程式多半可以快速完成指定行為,程式能否被團隊理解,仍取決於名稱、責任切分與結構安排。

生成內容若保留模糊命名、過長方法或混合責任,下一次修改時,開發者就得重新追查條件、資料與呼叫關係。

生成後整理可以先從局部可讀性著手。開發者不需要一次改動整個模組,可以沿著這次新增或修改的程式,確認名稱是否能表達業務語意、方法是否承擔過多工作,以及程式位置是否符合模組責任。

命名、抽取與結構調整會彼此牽動。清楚命名能暴露責任混合,抽取方法能讓業務規則形成可閱讀的步驟,結構調整能把責任放回適合的位置。

這三項整理需要搭配測試進行,避免整理時改掉原有行為。

命名要反映業務語意

名稱是開發者理解程式的第一層線索。類別、方法、變數與事件名稱若能直接表達業務概念,閱讀者不用立刻展開實作,就能先理解這段程式處理的情境。若名稱只描述技術動作,開發者就需要閱讀更多程式,才能判斷它對系統行為的影響。

AI 常會產生過於籠統的名稱,例如只描述技術動作或流程步驟,卻沒有指出實際的業務意圖。這類名稱在單一方法中也許還能理解,程式規模擴大後,就會讓人分不清它處理的是哪一種資料與哪個情境。

例如,一個方法若負責判斷訂單是否能取消,名稱可以使用 canCancelOrder。若它負責執行取消流程,則可以使用 cancelOrder。這兩個名稱分別表達判斷與狀態變更,呼叫端可以直接看出操作是否會產生副作用。

業務用語也需要與需求、文件和測試保持一致。產品討論使用「保留庫存」,程式中卻出現 lockStockholdItemreserveQuantity 等不同說法,後續搜尋與溝通就容易產生落差。

團隊可以建立共同詞彙表,讓提示詞、程式碼、測試與文件採用同一組名稱。

命名整理也能協助辨識設計問題。一個方法很難取名時,常代表它同時處理多項責任。名稱需要包含「驗證、計算、儲存與通知」才能完整描述時,方法邊界大多已經過寬。

抽取方法要服務理解

抽取方法可以把複雜程式切成較容易閱讀的步驟。適當的抽取能讓主流程保留業務順序,細節放進具名方法中。閱讀者可以先看懂整體流程,需要深入某一步時再查看實作。

例如,訂單取消流程可能包含資格檢查、庫存回補、退款建立與事件發布。若所有內容都寫在同一個方法中,閱讀者需要同時處理大量條件與技術細節。

經過抽取後,主流程可以呈現為檢查取消資格、回補庫存、建立退款與發布取消事件,整體意圖會更清楚。

方法抽取需要依照可理解的責任邊界進行。若單純為了縮短行數而拆出 step1doProcessexecuteLogic,閱讀效果仍然有限。抽取後的方法名稱應該說明這段程式完成什麼業務動作,輸入與輸出也要保持清楚。

條件判斷也是常見的抽取位置。多個布林條件組合在一起時,可以抽成 isEligibleForRefundrequiresManualApproval 等具名判斷。原本需要逐一解讀欄位的條件式,便能轉成接近業務規則的敘述。

抽取後也要注意方法之間的資料傳遞。若一個方法需要十多個參數,或大量依賴外部可變狀態,責任範圍高機率仍然過大。開發者可以先整理資料物件,再確認這段邏輯應該由哪個模組負責。

結構調整要尊重架構邊界

局部程式可讀性改善後,開發者還需要確認程式是否放在適合的位置。清楚的方法與名稱若被放進責任不符的模組,後續修改仍會牽動額外範圍,也容易讓依賴方向變得混亂。

例如,控制器可以負責接收請求、轉換輸入與回傳結果。訂單是否能取消、退款金額如何計算,以及庫存如何回補,多半需要放在應用服務(Application)或領域(Domain)層處理。

若這些規則留在控制器中,未來其他入口需要執行相同行為時,高機率會複製邏輯,或直接依賴控制器。

結構調整可以從責任與變更原因判斷。會因業務規則變動而修改的程式,可以集中在處理該業務概念的模組。會因資料庫技術改變而修改的程式,則放在資料存取區域。

當不同變更原因混在同一個類別中,後續修改便容易影響無關功能。

跨模組依賴也要一併檢查。為了取得一筆資料而直接引用另一個模組的內部類別,短期內能快速完成需求,卻會讓兩個模組共享實作細節。

較穩定的做法是透過公開介面、應用服務或事件交換資訊,讓模組邊界維持清楚。

結構調整的範圍需要配合這次變更控制。若發現較大的架構問題,可以先處理直接影響目前功能的部分,其他項目則建立可追蹤的改善工作。

每次生成後都完成一小段責任歸位,系統結構才不會被多次小變更推歪。

如何把重構後驗證放進工作流

重構完成後,需要用驗證證明行為沒有改變

重構會調整程式內部的名稱、方法切分、責任位置與依賴關係,預期保留原有外部行為。

這項工作若只依靠開發者閱讀程式確認,很難涵蓋所有邊界條件與整合影響。團隊需要把驗證放進重構流程,留下可重複執行的證據。

AI 參與重構後,驗證的重要性會進一步提高。AI 可以快速移動程式、抽取方法與改寫結構,也可能在整理過程中改變條件順序、例外處理或資料更新時機。程式可以編譯,畫面看起來也相同,某些邊界行為仍可能已經改變。

重構後驗證可以結合測試、靜態分析、程式碼審查與持續整合(Continuous Integration, CI)。開發者在本地完成快速檢查,提交後再由管線執行完整驗證,審查者則檢查證據與調整目的是否一致。

重構也需要有明確的停止條件。這裡的目標可以設定成「消除當下理解障礙」,即讓這次需要修改的程式變得容易閱讀、責任清楚,並且能安全完成目前需求。

當開發者已經能說明程式如何運作、修改範圍容易判斷,測試也能守住相關行為,就可以停止這一輪整理。

AI 容易繼續提出下一層抽象,例如再抽一個介面、再拆一層服務、再建立一組通用元件。這些建議不代表都需要立即採用。

若每次看到可以改善的地方就繼續展開重構,原本局部的需求修改可能快速擴散到相鄰模組,測試、審查與回復範圍也會跟著增加。

開發者應該在開始重構前先定義範圍,例如「讓這段訂單取消流程可以被理解與測試」,完成後就停止。

其他架構問題若確實需要處理,可以另外記錄改善工作。這樣能讓 AI 協助整理程式,也能避免重構變成沒有明確終點的抽象化活動。

重構前先建立測試保護

重構開始前,團隊需要先確認現有行為是否有足夠的測試保護。

測試提供的是目前系統行為紀錄,讓開發者在調整內部結構後,能檢查重要輸入、輸出與副作用。缺少這層保護時,重構容易夾帶無意識的功能變更。

測試保護不需要一開始就涵蓋整個模組。開發者可以先找出這次重構會碰到的主要流程、條件分支與系統邊界,再補上能固定現有行為的測試。

例如準備移動退款計算邏輯前,可以先建立一般退款、部分退款、不可退款與重複請求等案例。

遺留程式若難以建立細部單元測試,可以先使用特徵測試(Characterization Test)記錄目前輸出。

這類測試的作用,是先建立一條可比較的基準,用來確認重構或整理後的外部行為沒有被意外改變。團隊在釐清需求後,再逐步把這些案例改寫成具有明確業務意圖的測試。

測試也要涵蓋重要副作用,例如資料庫狀態、事件發布、外部服務呼叫與交易結果。只驗證方法回傳值,可能無法發現重構後改變了資料更新順序,或在失敗情境下多送出一次事件。

當 AI 協助建立測試時,開發者仍要確認案例來源。測試需要對應需求規則、既有系統行為與已知事故,避免 AI 只根據目前實作產生一組與程式共享相同假設的案例。

哪些部分需要測試保護,可以依照實際的變更風險與回復難度決定。測試能清楚說明預期行為後,才適合作為重構依據。

重構後要確認行為不變

重構完成後,開發者需要重新執行相關測試,確認原本受保護的行為仍然成立。這項檢查除了看測試是否通過,也要看測試範圍是否涵蓋這次調整造成的依賴變化。

局部方法抽取可以先執行單元測試。若重構涉及模組移動、資料存取、交易邊界或事件流程,則需要加入整合測試與契約測試。跨越多個服務的關鍵流程,可以再透過端對端測試確認主要使用情境。

某些行為差異不容易透過一般斷言發現。例如查詢次數增加、事件順序改變、日誌欄位遺失,或錯誤訊息從可辨識的業務錯誤變成通用系統錯誤。團隊可以搭配效能測試、快照測試、日誌檢查與執行追蹤,確認這些非功能行為。

重構後也要檢查靜態結果。型別檢查、程式碼掃描、循環依賴分析與架構測試,可以確認新的結構沒有違反既有規則。當類別被移動或介面被重新抽取時,這類檢查能找出錯誤依賴與未預期公開的範圍。

若重構同時改變了功能行為,團隊應將兩類修改分開說明。行為變更需要新的需求依據與驗收條件,結構變更需要證明既有行為受到保護。清楚區分後,測試失敗時較容易判斷來源,審查者也能針對不同風險檢查。

讓重構與審查相互支援

重構完成並通過自動化檢查後,仍需要透過程式碼審查確認結構調整是否提升可理解性。

測試可以證明部分行為沒有改變,新的名稱是否清楚、責任是否放在適合位置,以及依賴方向是否合理,仍要由審查者判斷。

提交重構變更時,開發者可以說明原本存在的理解問題、採用的調整方式、受影響範圍與驗證結果。審查者看到這些資訊後,可以沿著修改目的檢查程式,不必從大量差異中猜測每個移動與改名的理由。

功能修改與大範圍重構混在同一個拉取請求,會增加審查的理解負擔。

團隊可以先完成有測試保護的局部重構,再提交功能調整。也可以在同一項需求中使用不同提交區分結構變更與行為變更,讓審查者分段確認程式行為與設計選擇。

審查意見若反覆出現,例如命名模糊、控制器承擔業務邏輯,或跨模組直接引用內部類別,團隊可以將這些規則轉成檢查清單、架構測試或靜態分析規則。後續生成與重構便能較早得到回饋。

重構、驗證與審查形成固定循環後,團隊能以較小批次改善程式結構。每次生成內容進入主幹前,都會經過測試保護、結構整理、自動檢查與人工判斷。可讀性與修改安全,會變成流程中看得見的工程條件。

重點摘要

  • AI 生成完成後,內容仍屬於候選變更,需要經過需求、架構、測試與副作用檢查,才能進入主幹。
  • 開發者需要回到需求意圖,確認 AI 採用的假設是否符合產品規則、失敗情境與既有系統限制。
  • 架構規範需要落到呼叫路徑、資料流與依賴方向,才能檢查責任是否放對位置。
  • 生成後即整理適合趁上下文還清楚時進行,將提示詞、對話與臨時判斷轉成程式名稱、結構、註解或架構決策紀錄。
  • 命名、抽取方法與結構調整,目標是讓後續開發者能從程式看出業務意圖、責任邊界與修改影響範圍。
  • 小批次整理能讓程式碼審查聚焦在模組責任、錯誤處理與資料一致性,減少審查者辨識雜訊的時間。
  • 臨時取捨若要保留,需要留下原因、限制與後續處理條件,避免被 AI 或後續開發者當成正式慣例。
  • 重構前要先建立測試保護,尤其是主要流程、條件分支、系統邊界與重要副作用。
  • 重構後要重新執行測試、靜態分析與架構檢查,確認行為、依賴與公開範圍沒有出現未預期改變。
  • 重構需要明確停止條件,完成當下理解障礙的整理後就先停下來,其他架構問題再記錄成可追蹤工作。

上一篇
Day 19. 技術債與 AI 債:當快速產出開始侵蝕系統修改能力
下一篇
Day 21. 架構的核心:平衡變更成本、團隊能力與演化空間
系列文
AI 時代下,如何建立真正可持續的軟體交付能力22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言