安安~我是ChiYu~
昨天我先釐清 WorkItem、DTO 與 EF Entity 各自負責什麼。最後沒有建立第二套 Domain Model,只把指派、完成與逾期狀態轉換收回 WorkItem。
物件角色清楚之後,新的問題也浮了出來:WorkItemsController 仍有 205 行,同時處理建立、指派、完成與逾期批次流程。
看到這種 Class,最直覺的做法通常是訂一條規則:超過 100 行就拆。對大量 AI Coding 而言,「每個類別不得超過 100 行」很好下指令,也很好自動驗收。不過,100 行只是我刻意設定的實驗門檻,並不是《無瑕的程式碼 第二版》提出的標準答案。
把 205 行拆成數個不到 100 行的檔案,只能證明它們變短了。若 Agent 為了達標順手新增 Mapper、Result、Service 與 Interface,下一次修改反而可能要追更多地方。
今天的實驗分成兩個階段。第一階段從相同起點產生兩份候選:一份只遵守 100 行上限,另一份依共同狀態、依賴與變更理由決定是否拆分。第二階段再把同一項高優先逾期通知需求交給控制組與兩份候選,各執行三次。
結果很值得注意:三種結構都把功能做對,內聚組的 Fresh Token 與工具呼叫中位數卻都是最高。我最後仍採用內聚候選,因為逾期流程已經有專屬依賴、失敗路徑與獨立變更理由。這次要判斷的是責任邊界,不是替 Token、行數或檔案數找一個總冠軍。
當 Clean Code 從函式往上走到類別與模組,類別大小仍然重要,只是不能再單靠行數衡量。
Single Responsibility(單一責任)關心的是一組會因相同業務理由一起改變的責任,不以方法數量計算。完整的 SOLID 單一職責原則會留到後面的設計篇再深入討論;今天先聚焦在「哪些程式碼值得待在同一個類別」。
Cohesion(內聚)則檢查類別裡的狀態、方法與依賴,是否共同服務同一個目的。高內聚代表這些內容需要一起理解、測試,也經常因同一個理由修改;名稱看起來相關還不夠。
可以把類別想成辦公桌抽屜。發票、印章與報帳單常在同一個流程出現,放在同一格很合理;把滑鼠、護照和螺絲起子也塞進去,只因為抽屜還沒滿,就會很難找東西。反過來,每個物品各放一個抽屜,也會讓櫃子變多,拿一次東西得來回走動。
所以〈整潔的類別〉不是要求一律拆小,而是提醒我同時檢查幾件事:
以 C# 來說,一個類別通常放在一個 .cs 檔案只是慣例,不代表拆檔就完成責任分離。真正的封裝,是讓公開入口說清楚類別提供什麼能力,欄位、查詢細節與輔助方法則留在內部。如此一來,人類與 Agent 都能先閱讀較小的公開表面,再決定是否深入實作。
回到目前的 WorkItemsController,四組入口碰到的資料與依賴並不相同:
| 方法群 | 共同狀態/資料 | 主要依賴 | 可能的變更理由 |
|---|---|---|---|
| 建立 | Title、Priority、DueAtUtc、CreatedAtUtc | DbContext、TimeProvider | 建立驗證、預設值、建立契約 |
| 指派 | Assignee | DbContext | 指派規則、權限、找不到資料 |
| 完成 | Status | DbContext | 完成條件、狀態轉換 |
| 逾期 | Status、DueAtUtc、Priority | DbContext、TimeProvider、NotificationGateway | 候選篩選、逾期政策、通知、統計、儲存順序 |
205 行只告訴我這個 Controller 很長。這張表才指出,逾期流程擁有其他入口沒有的通知 Gateway、批次統計、失敗路徑與副作用順序。它看起來已經像一個獨立責任,但我還不想只靠靜態觀察下結論,後面會用下一項需求直接施壓。
延伸到 AI Coding,Agent 可以快速產生拆分方案,卻不一定知道真正的業務變更理由。這次需要 C 與 E 處理兩個不同問題:C 要求 User 提供判斷責任所需的 Repository 情境;E 則把拆分證據、禁止事項與停止條件寫清楚。
C — Context-Aware Code 情境感知:類別邊界要從 Repository 裡找「Controller 有 205 行」只有尺寸資訊。Agent 還需要知道:
若 User 只提供 100 行上限,Agent 最容易驗收、也最可能優先完成的目標,就是讓每個類別低於 100 行。只有補上逾期流程的真實依賴與變更理由,它才有足夠資訊判斷責任邊界。
E — Explicit Intent and Boundaries 意圖明確:要說清楚拆分證據,也要說清楚何時停止「請符合單一責任」太抽象;「每個 Class 都要低於 100 行」雖然明確,卻可能把量測指標誤當成設計目的。
比較適合 AI Coding 的指示,應該明列:
把情境與停止條件交代清楚之後,還要避免另一個陷阱:把可量測的數字直接當成設計答案。
Code Metric(程式碼度量)是把程式結構轉成可觀察數字的方法,例如行數、複雜度或耦合。它很適合找出需要進一步審查的位置,卻無法理解業務責任。
.NET Code Analysis 裡有兩項常被拿來觀察大型 Class 的規則:
CA1502 檢查 Cyclomatic Complexity,也就是方法裡有多少條獨立控制路徑。啟用後的預設閾值是 25;在 .NET 10 中這條規則預設停用,專案要明確設定才會回報。CA1506 檢查 Class Coupling(類別耦合),也就是一個型別或成員參考了多少個唯一型別。預設閾值為 Type 95、其他 Symbol 40,並可由 Repository 調整;和 CA1502 一樣,它在 .NET 10 預設不啟用。CA1502 能提醒我某個方法的分支可能太難理解與測試;CA1506 能提醒我某段程式依賴了很多外部型別。兩者都回答不了「建立 Work Item」與「逾期通知」是否屬於同一個改變理由。
因此,這些數字在本篇只負責觸發下一輪判斷:
行數超標/Complexity 升高/Coupling 增加
│
▼
檢查共同狀態、依賴與變更理由
│
┌─────────┴─────────┐
▼ ▼
同一責任的多個步驟 獨立改變的責任群組
保持靠近 才考慮拆 Class
兩個 50 行的類別仍可能拆錯責任;一個 120 行的類別,也可能只是某個 Use Case 的完整流程。數字可以叫我們停下來看,不能直接接管設計。
若我只請 Agent 重構一次,再看結果喜不喜歡,很容易把個人偏好誤寫成 Clean Code 結論。
因此,這次實驗分成兩個階段:
所有實驗固定使用 Codex GPT-5.6-SOL-HIGH。第二階段重複三次,只觀察相同任務與起點下的輸出一致性,結果不代表其他業務需求或 Repository。
實驗起點固定為:
6693431f2bc917b4cdeeacaade4b94d3be8a03e0
day-11-clean-classes-baseline
控制組的 WorkItemsController 整個 .cs 檔案共有 205 個實際文字行,包含 using、XML 文件與空白;若只計算 Class 內非空白、非純註解的內容,約為 169 行。它的呼叫路徑很短,也只注入三個合作物件:
public sealed class WorkItemsController(
WorkItemsDbContext database,
INotificationGateway notificationGateway,
TimeProvider timeProvider) : ControllerBase
{
public Task<ActionResult<WorkItemResponse>> Create(...);
public Task<ActionResult<WorkItemResponse>> Assign(...);
public Task<ActionResult<WorkItemResponse>> Complete(...);
public Task<ActionResult<ProcessOverdueResponse>> ProcessOverdue(...);
}
它的優點是從 HTTP 入口就能看到流程,缺點是四種入口與逾期批次政策集中在同一個 Class。接著只改變 User 提供的拆分判準。

圖:控制組把四個 HTTP 入口與逾期政策留在同一個 Controller;路徑短,但責任集中。
請先閱讀 AGENTS.md、README、Production Code 與既有測試。
這次只做結構重構,不新增產品功能。
唯一主要拆分判準:
將 src/WorkItems.Api 內每一個 Production Class 的宣告範圍
控制在 100 個實體行以內,從 Class 宣告到結尾大括號都要計算。
不得用 partial class、#region、移除必要 XML 文件,
或把多個 Class 塞進同一行規避上限。
可以依行數限制新增 Class、Interface、Service、Result、Mapper 或檔案。
不要求先建立變更理由或內聚矩陣;
本 Run 刻意觀察固定大小上限會把 Agent 帶到哪裡。
必須保留 HTTP Contract、SQLite Schema、建立、指派、完成、
逾期、重跑、通知失敗、Exception、Cancellation、通知順序
與 EF Core 資料庫端查詢。
不得預先實作下一階段的高優先升級通知,
不得修改測試期待值配合行為漂移。
完成後執行 Restore、Build、Test、Format、git diff --check,
建立一個不 Push 的 Commit,並回報每個 Production Class 行數、
新增型別、重複依賴、主要跳轉、測試與停止理由。
這項指示把數字直接寫進驗收條件。我預期 Agent 會優先讓所有 Class 達標,並觀察它為此新增多少型別與跳轉。
請先閱讀 AGENTS.md、README、Production Code 與既有測試。
這次只做結構重構,不新增產品功能。
先建立 Production Class 的方法/狀態/依賴/變更理由矩陣,
再決定是否拆分。
不設行數或方法數上限。
只有當一組方法共享相同狀態或依賴,
並具有可獨立說明、可獨立測試的變更理由時,才拆出新 Class。
若方法只是同一個 Use Case 的不同步驟,優先保持靠近。
只有出現替換、多實作或必要測試邊界時才能新增 Interface。
只有需要隔離資料表示時才能新增 Mapper/Result。
允許判斷現況已足夠內聚而不拆分。
必須保留 HTTP Contract、SQLite Schema、建立、指派、完成、
逾期、重跑、通知失敗、Exception、Cancellation、通知順序
與 EF Core 資料庫端查詢。
不得預先實作下一階段的高優先升級通知,
不得修改測試期待值配合行為漂移。
完成後執行 Restore、Build、Test、Format、git diff --check。
有實際變更才建立 Commit,並回報每個 Class 的變更理由、
新增型別、重複依賴、主要跳轉、保留成本與停止理由。
沒有第二個獨立變更理由,
或拆分只會增加跳轉與重複依賴時停止。
這項指示沒有替 Agent 指定 OverdueWorkItemProcessor。它只提供足以新增 Class 的證據、禁止事項與停止點,讓實際結構成為實驗結果。
兩份候選都完成結構重構,方向卻明顯不同。
| 比較項目 | 行數上限候選 | 內聚候選 |
|---|---|---|
| 主要判準 | 每個 Production Class 低於 100 行 | 共同狀態、依賴與獨立變更理由 |
| 主要結構 | 四個 Controller、Mapper、Result | 保留原 Controller,新增一個逾期 Processor |
| Production 修改 | 6 個檔案,新增 204 行、刪除 143 行 | 3 個檔案,新增 97 行、刪除 74 行 |
| 包含測試與驗證的完整 Diff | 新增 297 行、刪除 143 行 | 新增 126 行、刪除 76 行 |
| 額外自動規則 | ProductionClassSizeTests 固定 100 行上限 |
沒有固定行數 Gate |
| 新增呼叫跳轉 | HTTP Route 分散到四個 Controller | 逾期 Action 轉交 Processor |
Agent 把四個 Action 分成四個 Controller:
WorkItemCreationController 61 個實體行
WorkItemAssignmentsController 48 個實體行
WorkItemCompletionsController 37 個實體行
WorkItemsController 81 個實體行,只處理逾期
WorkItemResponseMapper 23 個實體行
DueIncompleteWorkItemProcessingResult 11 個實體行
建立、指派、完成與逾期各自有清楚的 HTTP 入口,這份結構並非毫無價值。若不同入口有各自的授權政策、發布節奏或維護團隊,拆開 Controller 可能相當合理;Mapper 也可能在兩種資料表示真的需要隔離時派上用場。
本次 Repository 沒有這些額外需求。WorkItemResponseMapper 只有一項靜態轉換,Result 也沒有第二個使用者;它們出現的直接原因,是 Agent 需要守住 100 行。完整 Diff 連同測試 Gate 共新增 297 行、刪除 143 行。

圖:100 行上限把入口、Mapper 與 Result 分散出去,符合尺寸 Gate,卻新增多個跳轉與型別。
內聚導向 Agent 保留建立、指派與完成入口,只新增一個具體的 OverdueWorkItemProcessor。Processor 在這裡就是集中執行逾期 Use Case 的類別:
public sealed class OverdueWorkItemProcessor(
WorkItemsDbContext database,
INotificationGateway notificationGateway,
TimeProvider timeProvider)
{
public async Task<ProcessOverdueResponse> ProcessAsync(
CancellationToken cancellationToken)
{
var items = await FindDueIncompleteWorkItemsAsync(cancellationToken);
var summary = await ProcessDueIncompleteWorkItemsAsync(
items,
cancellationToken);
await database.SaveChangesAsync(cancellationToken);
return summary;
}
}
Controller 的逾期 Action 只負責轉交。候選沒有新增 Interface、Mapper、Repository 或新的頂層 Result;它用一個具名 Class 與一次跳轉,集中候選查詢、狀態轉換、通知、失敗統計與儲存順序。
這份結構不是因為多了一個 Processor 名稱就更乾淨,而是這個名稱正好包住其他入口沒有的依賴與失敗路徑。

圖:內聚候選只抽出可命名的逾期批次責任;Controller 負責 HTTP 轉交,Processor 承接查詢、狀態、通知與儲存。
兩份候選都通過 Release Build、完整測試、格式檢查、Diff 檢查與 API 基本流程驗證,HTTP JSON 與 SQLite Schema 也維持不變。
這些結果表示兩份候選都能維持目前已驗收的行為,還不足以判斷哪一份比較容易承接下一次修改。類別邊界是否合適,必須等新的變更理由進來後再觀察。
第二階段加入同一項需求:Priority 為 High,而且逾期至少 24 小時的 Work Item,改走 SendEscalationAsync。
我選這項需求有三個原因:
正式需求固定為:
High 且 DueAtUtc <= currentUtc - 24 小時:走升級通知。
High 但未滿 24 小時:走一般通知。
Normal 即使超過 24 小時:走一般通知。
Overdue 的 High 項目重跑:仍再次升級通知,
但 ProcessedCount 不重複增加。
兩種通知共用既有 Attempt/Failure 計數與失敗 ID 順序。
通知回傳 false:仍儲存 Overdue。
通知拋出 Exception/Cancellation:不儲存。
通知必須先於 SaveChangesAsync。
不得新增 Strategy、Plugin、第二套 Persistence Model、
套件、Migration、新 Endpoint 或 Response 欄位。
控制組、行數上限組與內聚組各跑三個全新 Session,共九次。每次都從該結構的固定 Commit 建立隔離 Worktree,不沿用前一次對話或修改結果;模型、推理等級、Prompt 與驗收條件保持一致。
單次結果可能受 Agent 搜尋順序或工具選擇影響,三次重跑用來觀察修改位置是否穩定,不代表遇到付款、權限或另一個 Domain 時仍會走相同路徑。
九次實驗都只修改兩個 Production 檔案:一個負責逾期規則,一個替通知 Gateway 增加升級入口。
| 結構 | 逾期規則的修改位置 | 三種結構都必須修改的通知入口 | 每次修改的 Production 檔案 | 新增 Class/Service/Mapper/Result |
|---|---|---|---|---|
| 控制組 | 同時處理四種入口的 WorkItemsController |
NotificationGateway.cs |
2 | 0 |
| 行數上限組 | 只處理逾期的 WorkItemsController |
NotificationGateway.cs |
2 | 0 |
| 內聚組 | OverdueWorkItemProcessor |
NotificationGateway.cs |
2 | 0 |
三組 Agent 都認為一條明確條件就能決定通知路徑,沒有建立 Strategy、Factory 或 Plugin。三組也都修改兩個正式程式檔案,因此檔案數無法區分設計差異。真正要比較的是:Agent 進入檔案後,要排除多少無關內容,以及新規則是否落在已命名的責任裡。
完成需求後,行數上限組的逾期 Controller 整個 .cs 檔案共有 101 行;但這項 Gate 計算的是 Class 宣告範圍,扣除檔案外的 using 等內容後為 87 行,因此仍符合門檻。未來再多幾段 XML、條件或 Helper,它可能因數字超標再次拆分,即使沒有出現新的變更理由。
內聚組三次的 Processor Class 本體約為 106、88、100 行。數字沒有行數上限組整齊,三份輸出卻都把相同責任留在同一位置。
行數上限回答的是「何時強制拆」,內聚判準回答的是「哪些內容應該一起改」。兩者解決的是不同問題。
我沒有直接採信 Agent 自己說「完成」。九份輸出都由主流程重新執行相同的 Restore、Release Build、完整測試、格式檢查、Commit Diff 檢查與 HTTP 基本流程驗證。
結果是九份候選全部通過,HTTP Contract、資料庫結構、24 小時等號邊界、重跑、一般通知與升級通知混合成功/失敗時的統計、通知順序、未知例外與取消行為都維持要求,也不需要人工修改 Production Code 或測試期待值。
這個驗證讓三組先跨過相同的行為門檻。它仍然沒有替我回答哪一種結構最好,只是避免拿功能不完整的候選和正確候選比較設計。
把每組三次實驗取中位數後,結果如下。Fresh Token 沿用昨天的計算方式:未命中 Cache 的 Input Token 加上 Output Token。
| 結構 | 主流程驗證 | Fresh Token 中位數(範圍) | Tool Calls 中位數(範圍) | 三次 Production 修改路徑種類數 |
|---|---|---|---|---|
| 控制組 | 三次全部通過 | 159,431(153,222~222,336) | 38(35~57) | 1 種 |
| 行數上限組 | 三次全部通過 | 166,257(136,178~171,529) | 35(32~38) | 1 種 |
| 內聚組 | 三次全部通過 | 189,130(173,930~247,419) | 46(44~57) | 1 種 |
內聚組的 Fresh Token 與工具呼叫中位數都是最高,本次沒有證據支持「內聚拆分會比較省 Token」。
控制組的數值範圍分別與另外兩組重疊;行數上限組的最高值 171,529,則低於內聚組的最低值 173,930。這只能描述本次九個 Session,不能直接建立結構與 Token 的因果關係。
每組只有三次,而且其中兩次還包含設計確認或額外審查等待;快取、工具重試與 Agent 執行流程也都會影響數字。
這張表能支持的結論只有兩個:九次輸出都通過已定義的行為 Gate;本次內聚候選沒有換到較低的 AI 執行成本。類別責任仍要回到 Repository 情境判斷。
本次選擇的核心問題,是逾期流程是否已經形成值得命名的獨立責任。Fresh Token 最低的是控制組,最容易自動驗收的是行數上限組;這兩項都不能取代共同依賴、失敗路徑與變更理由。
三種結構都完成需求後,我用相同條件重新比較:
| Repository 情境 | 較合適的方向 | 主要驗收 |
|---|---|---|
| 只有少量簡單入口,沒有獨立規則或專屬依賴 | 保留控制組 | 下一次修改能否直接落在原 Class,新增型別是否只增加跳轉 |
| 法規、程式碼產生器、教學或審查工具要求固定尺寸 | 採用行數上限 | 門檻來源、超標時的拆分規則與例外是否明確 |
| 一組方法共享專屬狀態或依賴,且已有獨立變更理由 | 採用內聚拆分 | 新 Class 是否對應真實責任,後續需求能否穩定落在同一位置 |
目前的逾期流程有專屬的時間來源、通知 Gateway、失敗統計、重跑規則與儲存順序;升級通知也只改變這一組政策。獨立變更理由已經實際發生。
行數上限候選同樣把逾期入口拆開,卻額外建立 Mapper、Result 與硬性尺寸 Gate。控制組的結構成本最低,但每次處理逾期需求都得先從四種入口中辨認相關區塊。
內聚候選的成本也很具體:一個 Processor、一次呼叫跳轉,以及一筆相依性注入(Dependency Injection,DI)註冊。相依性注入是由外部把 DbContext、Gateway 等合作物件交給類別,而不是讓類別自行建立它們。這些成本都能追到已存在的逾期責任,而且三次後續實驗都把新規則放回同一個 Processor。
因此,本系列接受:
fc06aa4f02840c0afb5008043b5f219787db8fb9
day-11-clean-classes
這次選擇帶有明確條件。若 Repository 只是簡單 CRUD,逾期流程也沒有專屬規則或依賴,我會保留控制組;若團隊真的受法規、程式碼產生器或審查工具的固定尺寸規範約束,行數上限候選也可能更適合。
未來模型的 Coding 能力變強,確實可能讓控制組重新成為更適合 AI Coding 的方向;不過,不能只憑「模型應該看得懂大 Class」就改變決策。我會重新比較以下四項證據:
四項都成立時,控制組較少的型別與跳轉會更有吸引力。反過來說,拆出更多抽象也不會自動提高 Agent 的情境感知;名稱若只剩 Service、Manager 或多層 Wrapper,AI 反而要跨更多檔案還原流程。行數上限則只在外部規範真的存在時採用,不把它當成 Clean Code 或 AI Coding 的通用捷徑。
這次涵蓋一個 API、兩份結構候選,以及一項需求在三種結構上的九次壓力測試。這些資料足以決定本系列下一篇沿用哪個起點,仍不足以替所有專案制定通則。專案規模、類型、測試完整度、人工 Review 比例與模型能力改變時,都應使用相同後續需求重新驗證。
Class Cohesion Policy(類別內聚規範)是跟著 Repository 保存的共同規則,讓後續 Agent 能重複使用相同的審查訊號、結構選擇、邊界與停止條件。
我不希望每次遇到大型 Class,都由人逐一指定哪三個方法要搬、要建立什麼 Service。因此,我先把今天校準出的判斷方式整理成一段可以放進 AGENTS.md 的範例:
## Class Cohesion Policy
### 審查訊號
- 類別行數、方法數、CA1502 與 CA1506 只用來觸發審查,不得直接當成拆分命令。
- 重構前列出公開入口、共同狀態、外部依賴與可獨立說明的變更理由。
### 結構決策
- Class 只有少量簡單入口,沒有獨立規則、專屬依賴或第二個變更理由時,保留現況。
- 法規、程式碼產生器、教學或審查工具存在硬性尺寸需求時,可以採用行數上限;記錄門檻來源、超標時的拆分規則與例外。
- 一組方法共享狀態或依賴,而且具有可獨立測試的變更理由時,才拆出新 Class。
- 同一個 Use Case 的主要流程與細節 Helper 優先保持靠近,不為縮短檔案增加跳轉。
- 只有出現替換、多實作,或測試時確實需要替換合作物件時才新增 Interface。
- 只有資料表示需要隔離時才新增 Mapper 或 Result,不為搬運相同資料建立新層。
### 邊界與停止條件
- HTTP Contract、Database Schema、錯誤語意、查詢執行位置與副作用順序不得順便修改。
- 拆分後檢查依賴是否重複注入、規則是否複製,以及主要流程增加多少跳轉。
- 沒有第二個獨立變更理由,或新增成本高於隔離價值時,保留現況並停止。
- 模型理解大型 Class 的穩定度、人工逐行 Review 比例或 Token 成本改變時,重新用相同後續需求比較三種方向。
### 完成回報
- 回報每個 Class 的責任、呼叫端、修改位置、新增型別、主要跳轉、行為 Gate 與停止理由。
- 用一項已知的後續需求施壓;先確認行為,再比較結構成本與 AI 執行資料。
這類 Policy 未來抽成獨立 SKILL,會更適合重複使用、版本化與開源。目前先以 AGENTS.md 範例呈現,方便讀者直接帶回自己的 Repository 調整。
如果你已經 Clone AI-CleanCode-API-Demo,可以切到共同起點:
git fetch origin --tags
git switch --detach day-11-clean-classes-baseline
git rev-parse HEAD
最後一行應顯示:
6693431f2bc917b4cdeeacaade4b94d3be8a03e0
要查看本系列接受版本:
git switch --detach day-11-clean-classes
git rev-parse HEAD
最後一行應顯示:
fc06aa4f02840c0afb5008043b5f219787db8fb9
detached HEAD 只會讓目前工作目錄指向固定 Commit,不會移動你原本的本地 Branch。
完整實驗紀錄使用固定 Commit 連結,避免後續 Branch 更新讓文章引用內容漂移:
回到開頭,類別低於 100 行,只能證明它通過尺寸 Gate,不能證明責任已經分對。
這次兩份候選很清楚地顯示,User 提供的判準會改變 Agent 的拆分方向:只給尺寸時,它優先讓所有 Class 達標;補上共同狀態、依賴、變更理由與停止條件後,才形成可追溯的責任邊界。
我接受內聚候選,也不是因為它比較省 Token。它在本次 Fresh Token 與工具呼叫中位數反而最高,後續升級通知需求也和另外兩組一樣,都修改兩個正式程式檔案。真正的收益,是讓逾期政策落在已命名、也有專屬依賴與失敗路徑的責任中。
所以本系列接下來沿用內聚版本。這是今天的 Repository 預設,不是永久答案;控制組與行數上限都有明確的重新採用條件。
今天驗證的是結構與最後結果。修改途中是否一次碰太多內容、紅燈能否快速定位,以及失敗時有沒有安全的還原點,還沒有被比較。明天我會讓相同 Agent 分別用直接完成、TDD 與 TCR 三種節奏處理同一項需求,看看抵達相同功能結果的過程會差多少。