安安~我是ChiYu~
昨天整理完通知的行為契約、Consumer 需要的能力與原始碼依賴方向後,系列接續版本仍只有一個 Production Project。IWorkItemNotificationSender 由高階 Use Case 擁有,兩個通知 Adapter 反過來實作它。不過,所有 Production Code 仍編譯進同一個 Assembly,Build 還無法阻止不同責任之間出現不該有的參考。
看到這裡,我也很容易直接把程式碼拆成 Domain、Application、Infrastructure 與 Api。建立 .csproj、搬移 Namespace、補上 Project Reference,再畫出一張箭頭朝內的依賴圖,對 AI Agent 來說並不困難。
九份候選跑完後,真正困難的果然不是做出無循環的圖,而是決定每個 Assembly 裡應該裝什麼。技術分層有一份候選讓只需要 SLA 的 Reporter 取得 Assignment Policy,因而被拒絕;功能元件三次都守住 Consumer 邊界,卻一次建立七個 Project;元件原則先行的三次結果,則都只抽出 API 與 Reporter 真正共用的 WorkItems.ServiceLevel。
本系列最後接受原則先行 Run 02。不是因為 Project 最少一定最好,而是目前唯一能證明的共同重用內容只有 SLA 規則,而且這份候選還把 Reporter 案例放進一般測試流程。今天要回答的問題就是:每一條新增的元件邊界,究竟在保護哪一群 Consumer,又為什麼值得現在支付建置與發布成本?
前面談 SOLID 時,判斷單位大多是 Class、Interface 與它們的 Consumer。系統繼續長大後,一個 Consumer 可能只想重用其中幾個 Class,卻因為參考某個 Assembly,被迫承擔整組程式碼的升級與驗證成本。
這裡所說的 Component(元件),是由多個 Class 組成,並具有建置、依賴、重用或發布意義的設計單位,不是前端畫面上的 UI Component。
〈元件原則〉把問題分成兩組:REP、CCP、CRP 檢查哪些內容有理由待在一起;ADP、SDP、SAP 再檢查元件之間如何相依。
| 類型 | 原則 | 白話理解 | 今天怎麼觀察 |
|---|---|---|---|
| 元件內聚 | REP:重用/發布等價原則 | 被別人重用的程式碼,要有可辨識的發布與版本責任。 | API 與 Reporter 共用的程式碼,有沒有形成合理的候選發布單位? |
| 元件內聚 | CCP:共同封閉原則 | 因相同 Actor、相同原因改變的內容,應集中在同一個元件。 | SLA 門檻改變時,修改與重新驗證會落在哪裡? |
| 元件內聚 | CRP:共同重用原則 | Consumer 不該承擔自己用不到的公開內容與升級成本。 | Reporter 是否被迫依賴 Entity、通知、持久化或 Assignment Policy? |
| 元件耦合 | ADP:非循環依賴原則 | 編譯期元件圖不能繞一圈又回到自己。 | Production ProjectReference 能不能形成單向無環圖? |
| 元件耦合 | SDP:穩定依賴原則 | 較容易改的元件,應依賴較難改動、被更多 Consumer 使用的元件。 | API 與 Reporter 是否共同指向 SLA 元件? |
| 元件耦合 | SAP:穩定抽象原則 | 越穩定的元件,越需要適量抽象承接變化。 | SLA 元件目前有沒有真實替換或擴充壓力? |
六項原則不會各自產生一個可以加總的品質分數。CCP 希望一起改的內容留在一起,CRP 則要求排除 Consumer 用不到的內容;REP 還要追問這個重用邊界是否真的具備版本與發布責任。
本篇先用 REP、CCP、CRP 找出「為什麼要放在一起」,再以 ADP、SDP、SAP 檢查形成的依賴圖。依賴圖沒有循環,只能證明 Build Graph 沒有繞回原點,不能證明元件內部放對了東西。
Robert C. Martin 早期是在大型 C++ 系統中,以 UML package 討論比 Class 更大的設計單位。那裡的 package 不能直接等同今天的 NuGet Package。接下來出現的 .csproj、Assembly、NuGet 與 Architecture Test,是我把元件原則套進 .NET 與 AI Coding 實驗後所做的對照,不是書中指定的實作方式。
| 實體 | 能提供什麼 | 單靠它還不能證明什麼 |
|---|---|---|
| Folder | 整理檔案與路徑。 | 不會阻止錯誤依賴,也沒有版本或發布能力。 |
| Namespace | 提供型別的邏輯分組與名稱範圍。 | 不等於 Assembly,也不會單獨形成編譯邊界。 |
.csproj Project |
定義建置輸入,並以 ProjectReference 形成編譯期依賴節點。 |
不代表它會獨立版本化或發布。 |
| Assembly | .NET 的部署、版本控制與重用基本單位。 | 產生 .dll 不代表內容已符合 REP、CCP 與 CRP。 |
| NuGet Package | 具有 ID、Version、Manifest 與相依資訊的發布容器。 | dotnet pack 成功不代表 API 相容,也不代表元件邊界合理。 |
今天先用 Project 與 Assembly 當作實驗節點。ProjectReference 能讓 Build 阻止未宣告的跨界參考,但候選新增的 .csproj 目前仍只是建置圖上的節點。沒有獨立版本、相容性說明、發布責任與 Consumer 升級路徑,就不能直接宣稱完整符合 REP。

圖:元件邊界越強,維護成本也越高;只有真實變更壓力出現時,才需要往上一層升級。
如果實驗裡只有現有 API 這一個 Consumer,幾乎每一種 Project 拆法都能找到理由,很難觀察共享 Assembly 是否夾帶使用者根本不需要的內容。
因此,我刻意新增一個可獨立建置與執行的 WorkItems.ServiceLevelReporter Console Project。它是實驗工具,不是已上線產品,也不是正式背景程式需求。它只製造一個具體問題:第二個程式只想重用 SLA 規則時,會不會被迫一起依賴 Entity、資料庫與通知功能?
Reporter 依序接收 Priority、DueAtUtc 與 CurrentUtc 三個參數,重用 API 既有的 ServiceLevelEscalationPolicy,最後只能輸出 Escalation 或 Regular。主流程固定兩個案例:
Escalation。Regular。兩個 Consumer 的需要很不一樣:
WorkItems.Api HTTP、逾期處理、資料、通知與 SLA 規則
WorkItems.ServiceLevelReporter 只有 SLA 規則
Reporter 不需要 Controller、HTTP Contract、EF Core、SQLite、通知 Provider,也不需要 AssignmentManagementEscalationPolicy。API 與 Reporter 必須共用唯一一份 SLA 規則,不能複製條件。
如果 Agent 把整套 Work Item Domain 都塞進共享 Project,Reporter 仍然可以執行,卻得承擔整個 Assembly 的發布與重新驗證成本。這就是 CRP 在今天真正要攔下的問題。
C — Context-Aware Code 情境感知 要我先提供 Repository 目前真的存在的情境:兩個 Consumer 共同使用 SLA 規則;目前沒有不同功能團隊、獨立部署、Package 版本或多套 Domain Model。
這些尚未出現的需求同樣重要。只給 Agent 一句「請依 Clean Architecture 模組化」,它只能用常見架構補完空白;資料夾可以很漂亮,邊界卻不一定對得上這個 Repository。
L — Localized Change 局部變更 的檢查範圍超過檔案數。下一次 SLA 門檻改變時,我還要看哪些 Project 需要重新 Build、哪些測試要重跑、哪些 Consumer 得跟著升級。
Reporter 只需要 SLA,卻因一行門檻調整而被迫接受整套 Domain 或整個 API 的更新,修改範圍仍然過大。
這兩項原則決定了今天的操作方式:先把 Consumer 與禁止依賴寫清楚,再觀察不同邊界指令會把同一個 Agent 帶往哪裡。
三種案例使用相同起點、需求、模型、推理強度、Reporter Oracle 與 API 行為驗收。每種案例各跑三個互不共享對話內容的新 Session,共九次正式實驗。
Prompt 同時改變多項邊界指示,因此結果只能當作三種策略的案例比較。以下名稱由本系列自行設計,《無瑕的程式碼 第二版》沒有這套分類。
| 實驗案例 | 交給 Agent 的邊界方向 | 我要觀察什麼 |
|---|---|---|
| 先依技術層拆 Project | 固定建立 Domain、Application、Infrastructure 與 API。 | Clean Architecture 的外形是否會產生過大的 Domain,讓 Reporter 取得無關內容? |
| 先依功能能力拆 Project | 依逾期處理、通知、持久化、Work Item 管理、SLA 與 Reporter 拆分。 | 共同變更是否更清楚,以及小型 API 會不會因此出現過多 Assembly? |
| 先分析元件原則再決定 | 先分析 REP、CCP、CRP、ADP、SDP、SAP,再建立最少必要邊界。 | Consumer 證據能否讓 Agent 停在目前真的需要的元件數量? |
三份 Prompt 最直接影響邊界決策的段落如下:
技術分層:即使某一層目前只有少數類別,也要保留技術分層 Project。
功能元件:即使部分功能元件目前只有少數類別,也要保留功能 Project。
元件原則先行:Project 數量不列入評分;每個新增 Project 都要提出
Consumer、共同變更、共同重用或發布理由。
完整 Prompt 保留在公開 Repository:
九份候選都要由主流程重新驗證。Restore、Release Build 與格式檢查確認專案能正常建置;完整測試與 API Smoke Test 守住既有行為;另外兩個 Reporter CLI 案例,確認新 Consumer 真的能獨立執行並得到預期結果。
兩個 Reporter 案例由主流程事先決定,在 Agent 交付後獨立執行。即使候選沒有替 Reporter 新增測試,也不能只靠自己挑選的案例宣布完成。
驗收還包含一條事前寫好的結構規則:承載 SLA 的 Project 不能包含 Assignment、EF、Notification 或 Controller。這條 Gate 能擋下已經明列的名稱,卻不會自行理解每個 Class 對 Reporter 是否必要。因此結構測試全綠後,User 仍要回到 Consumer 情境檢查 CRP。
九份候選中有八份通過;被拒絕的那一份雖然可以 Build、Test 與執行,卻讓 Reporter 依賴了明令排除的 Assignment Policy。三種策略的主要差異如下:
| 實驗案例 | Agent 建立的 Production 邊界 | Reporter 最後取得什麼 | 主要成本與結果 |
|---|---|---|---|
| 技術分層 | 5、6、5 個 Project,結果沒有完全收斂。 | Run 01 取得含 Entity 的 Domain;Run 03 還取得 Assignment Policy;Run 02 另抽出 SLA Project。 | 兩份通過,一份因跨越明列的 CRP 邊界被拒絕。 |
| 功能元件 | 三次都建立 7 個 Project。 | 只取得 SLA Project。 | 三份都通過,但搬移範圍、Reference 與 Build 節點最多。 |
| 元件原則先行 | 三次都保留 API,再新增 ServiceLevel 與 Reporter。 | 只取得 SLA Project。 | 三份都通過,元件圖一致,修改範圍也最小。 |
檔案數、行數與每次 Session 的完整資料都保留在公開實驗結果。接下來看每種邊界實際保護了什麼。
技術分層 Run 01 與 Run 03 都建立五個 Production Project:
WorkItems.Api
├── WorkItems.Application ──> WorkItems.Domain
├── WorkItems.Infrastructure ──> WorkItems.Application
│ └─> WorkItems.Domain
└── WorkItems.Domain
WorkItems.ServiceLevelReporter ──> WorkItems.Domain
這張 Production Reference Graph 是單向的,也沒有循環。Application 不引用 EF Core,具體資料與通知放進 Infrastructure,Reporter 也沒有直接依賴 API。ADP 在這個分析範圍內成立。
問題出在 Domain 裡放了什麼。
Run 01 把 WorkItem Entity 與 ServiceLevelEscalationPolicy 一起放進 Domain。它通過事前固定 Gate,因為規則沒有禁止 WorkItem Entity;但 Reporter 只需要 SLA,卻得參考同時包含狀態與資料模型的 Assembly。自動驗收沒有違規,不代表 CRP 已經成立。
Run 03 又把 AssignmentManagementEscalationPolicy 放進 Domain。Agent 回報 Reporter 沒有呼叫它,這只在原始碼使用層次成立;一旦參考 Domain Assembly,Reporter 就承擔整個 Assembly 的發布與重新驗證成本。這已跨越 Prompt 明列邊界,主流程因此拒絕候選。
Run 01 與 Run 03 顯示兩種問題:前者沒有違反已編碼規則,邊界仍然偏大;後者明確違規,可以由 Gate 擋下。只有自動規則與 Consumer 判斷一起存在,CRP 才不會被簡化成「有沒有呼叫某個 Class」。
Run 02 另外抽出只放 SLA 規則的 WorkItems.ServiceLevel:
WorkItems.ServiceLevelReporter ──> WorkItems.ServiceLevel
WorkItems.Api ───────────────────> WorkItems.ServiceLevel
WorkItems.Api ──> Application/Domain/Infrastructure
它守住 Reporter 的 CRP,代價是完整技術分層之外,再多一個共享政策 Project。同一份技術分層 Prompt 跑三次,Agent 仍交出兩種 Consumer 邊界。只告訴 AI「採用技術分層」,不會自動回答 Reporter 應取得整套 Domain,還是只取得 SLA 規則。
技術分層並沒有因此出局。多個 Host 共同使用整套 Domain/Application,而且需要阻止 EF Core、Web Framework 或 Vendor SDK 滲入核心時,我會採用這個方向。現在能證明的共同使用範圍只有 SLA,整套 Domain 還太大。
功能元件候選拆得更細:
WorkItems.Api
├── WorkItems.OverdueProcessing
├── WorkItems.Persistence
├── WorkItems.Notifications
├── WorkItems.ServiceLevel
└── WorkItems.WorkItemManagement
WorkItems.OverdueProcessing
├── WorkItems.Persistence
├── WorkItems.Notifications
├── WorkItems.ServiceLevel
└── WorkItems.WorkItemManagement
WorkItems.ServiceLevelReporter ──> WorkItems.ServiceLevel
三個 Session 都建立七個 Production Project。Reporter 只參考 SLA Project,通知與資料存取也分開。名稱確實比純技術分層更容易看出功能責任,但名稱仍只是線索;每個 Project 是否值得存在,還要看 Actor、Consumer、共同變更與發布需求。
拆 Project 也可能改變 Runtime 時序。功能元件 Run 03 與技術分層 Run 03 都把資料庫註冊搬進新的 Extension Method,結果在 Host 尚未完成設定前就讀取 Connection String,導致 API 測試失敗。Agent 最後找回「Host 完成設定後才解析 Connection String」的時序,原有測試期待值沒有被改弱。
ProjectReference 圖只能描述編譯期依賴,攔不住設定解析時序。這裡要靠 N — Non-Surprising Behavior 符合預期 驗收:Agent 可以搬 Project、Namespace 與服務註冊位置,API 的啟動時序與對外行為不能跟著改變。
功能元件目前缺少相應發布壓力。Notifications、Persistence 與 OverdueProcessing 仍由同一個 API 組裝與發布,部分 Project 只有少數類別,卻都需要自己的 .csproj、Lock File、Reference 與 Build 節點。
若這些功能未來出現不同 Consumer、團隊、權限、版本或部署週期,我會重新考慮功能元件。現在直接留下七個 Project,成本已經出現,支持它們獨立發布的需求卻還沒出現。
原則先行的三個 Session 都保留原本 API,只新增 ServiceLevel 與 Reporter:
WorkItems.Api ---------------------> WorkItems.ServiceLevel
WorkItems.ServiceLevelReporter ----> WorkItems.ServiceLevel
WorkItems.ServiceLevel 只承載 ServiceLevelEscalationPolicy。SLA 判斷沒有被改寫,只是移到新的 Project 與 Namespace;由 Assignment Management Actor 負責的政策繼續留在 API,沒有因為名稱同樣帶有 EscalationPolicy 就一起搬走。三份候選都通過行為與結構 Gate,也沒有搬動 EF Core、通知或逾期流程。
SDP 所說的穩定,主要來自依賴關係。被越多 Consumer 依賴,修改時要顧慮的對象通常越多,元件也越難隨意改動。
Martin 使用 Ca、Ce 與 I 描述這件事:
Ca:有多少外部元件依賴它
Ce:它依賴多少外部元件
I = Ce / (Ca + Ce)
I 越接近 0,表示元件在目前依賴圖中越穩定;越接近 1,表示它主要依賴別人,自己比較容易改。
SAP 另外使用 A 觀察抽象程度:
A = 抽象類別數 / 類別總數
A 與 I 可以放進 Main Sequence 一起觀察「很穩定卻完全具體」或「非常抽象卻沒人使用」的元件。不過,指標只能拉警報,不能直接當作品質分數。
Martin 的原始度量以 Class 耦合為單位。本篇為了觀察 .csproj 邊界,改用 Production ProjectReference 計算 I,但 A 仍以 Class 為單位。兩者粒度不同,所以我不計算正式 Distance;下面的數字只代表這組 .NET 實驗。
| 原則 | 這次能支持的判斷 |
|---|---|
| REP | API 與 Reporter 共同建置、重用同一份 SLA 規則;若未來獨立發布,ServiceLevel 是目前最小候選單位。現在還沒有版本化 Package,完整 REP 尚未成立。 |
| CCP | SLA 門檻由同一個 Service Level Actor 改變;Reporter 的 CLI 解析與 API 的 HTTP、資料流程各自分開。 |
| CRP | Reporter 只取得 SLA 規則,不必依賴 WorkItem Entity、通知、EF Core、SQLite 或 Assignment Policy。 |
| ADP | API 與 Reporter 單向指向 ServiceLevel,Production Graph 沒有循環。 |
| SDP | 以 ProjectReference 為本次分析單位,ServiceLevel 有兩個 Consumer、沒有向外參考,Ca = 2、Ce = 0、I = 0。兩個較易變的執行程式共同依賴它。 |
| SAP | ServiceLevel 目前只有一個具體政策,呈現「穩定但具體」的質化警示;現階段沒有第二個實作或替換壓力,不增加空 Interface。 |
SAP 的警示值得留下,但我不會為了讓 A 變大就建立沒有 Consumer 的 Interface。抽象要保護真實替換或擴充壓力,多一個檔案不會讓 SLA 門檻更容易修改。
原則先行只要求每條邊界提出證據,不會永遠得到最少 Project。如果五項功能都出現獨立 Consumer 與發布壓力,最後一樣可能留下五個元件。
| Repository 情境 | 邊界選擇 | 先確認的證據 |
|---|---|---|
| 只有單一 Host,沒有獨立 Consumer、版本或發布需求 | 保持單一 Project,先用 Folder 與 Namespace 整理 | 新增 Assembly 能隔離哪一項真實變更? |
| 多個 Host 共用 Domain/Application,而且要阻止 Framework 或 Vendor SDK 滲入核心 | 技術分層 | 共用核心的 Consumer、允許依賴方向與部署方式 |
| 功能由不同團隊維護,具有各自 Consumer、權限、版本或發布節奏 | 功能元件 | Actor、共同變更、獨立發布與 CRP 成本 |
| 多個 Consumer 只需要一小組穩定規則 | 共用 Assembly;出現獨立版本與發布需求後再升級成 Package | 共同重用內容、公開 Contract、相容與發布責任 |
技術分層與功能元件也能混合使用。大型系統可以先依功能切元件,再在單一功能內分離高階政策與低階 Adapter。元件原則負責檢查邊界理由,不要求整個 Repository 套用同一種外形。
Consumer/Actor/Release 壓力
↓
REP、CCP、CRP 內聚分析
↓
ADP、SDP、SAP 依賴分析
↓
Folder/Namespace/Project/Assembly/Package
目前已經出現第二個 Consumer,卻還沒有多個功能團隊、獨立發布或 Framework 隔離壓力。因此,只抽出 API 與 Reporter 共同使用的 SLA Assembly,比完整技術分層或七個功能元件更符合現況。
三份原則先行候選得到相同的 Production Graph。Run 02 額外把 Reporter 的兩個行為案例納入一般測試流程,所以未來每次執行 dotnet test 都會重新驗證 High/48 小時與 Normal/12 小時的結果。它沒有增加 Production Project,也沒有擴大 Reporter 的依賴。
因此我接受 Run 02。多出的測試程式碼不是免費的,但它能防止 SLA 規則與第二個 Consumer 在後續修改中悄悄分岔,這筆成本有明確用途。
本系列接下來沿用:
76de5b546bd07179676423cb7e336ba20add2f95。day-17-formal-principles-first-boundary-run-02。day-17-component-principles。讀者可以切到實驗起點:
git switch --detach day-17-component-principles-baseline
再切換到系列接續版本:
git switch --detach day-17-component-principles
也可以直接查看 Baseline 與系列接續版本的完整 Diff。
三種方向各跑三個 Session。技術分層平均包含正式驗證失敗的 Run 03,因此下表只能描述實際投入成本,不能把三組當成完全同品質候選。
| 實驗案例 | Fresh Input Token | Output Token | Tool Calls | 平均時間 | 主流程驗證 |
|---|---|---|---|---|---|
| 先依技術層拆 Project | 157,112 | 32,891 | 48.0 | 1,216.1 秒 | 兩次通過、一次失敗 |
| 先依功能能力拆 Project | 173,024 | 30,057 | 43.3 | 1,013.5 秒 | 三次通過 |
| 先分析元件原則再決定 | 113,412 | 20,684 | 48.0 | 752.1 秒 | 三次通過 |
這組案例中,原則先行的 Fresh Input、平均時間與修改範圍都較小。最直接的差異是它沒有大規模搬動既有 API,只抽出兩個 Consumer 真正共同使用的 SLA 規則;Build、Tests、Lock File 與重新驗證的範圍也隨之縮小。我推測這是 Token 降低的原因之一。
三種 Prompt 的內容與 Agent 決策路徑並不完全相同,因此不能把差異全部歸因於 Consumer 分析,也不能保證換一個 Repository 還會省下相同比例。
Tool Calls 沒有同步下降。原則先行與技術分層平均都是 48 次,高於功能元件的 43.3 次。Agent 仍要搜尋 Repository、分析邊界、執行測試並確認停止點;原則先行減少的是實際搬動與重新驗證的範圍,不是所有思考與工具操作。
Token 適合比較通過相近品質門檻後的執行成本,不能拿來替六項元件原則打分數。
前面幾篇已經示範過 Naming、Function、Model、Test 與 Provider Contract Policy。今天我再整理一份 Component Boundary Policy,示範如果要放進 AGENTS.md,可以怎麼要求 Agent 在拆 Project 前先找 Consumer 與發布證據。
## Component Boundary Policy
- 新增 Project、Assembly 或 Package 前,先列出實際 Consumer、Actor、共同變更原因、
共同重用內容,以及獨立 Build、Version、Release、Deploy 的需求。
- 只有單一 Host,且缺乏獨立 Consumer、版本與發布需求時,維持單一 Project;
先用 Folder、Namespace、Tests 與 Repository Policy 整理責任。
- 多個 Host 共用 Domain/Application,而且需要隔離 Framework、Persistence 或 Vendor SDK 時,
可以採用技術分層;必須回報共用核心的 Consumer 與允許依賴方向。
- 功能具有不同 Actor、Consumer、權限、生命週期、版本或發布節奏時,可以採用功能元件;
不得只因功能名稱不同就建立 Assembly。
- 多個 Consumer 只共同使用一小組穩定規則時,可以抽出共用 Assembly;
只有出現獨立版本、相容與發布需求時,才升級成 Package。
- 技術分層與功能元件可以混合;每條 ProjectReference 都必須對回 Consumer、
共同變更或禁止依賴,不能要求整個 Repository 套用單一模板。
- 先用 REP/CCP/CRP 建立元件內聚分析,再用 ADP/SDP/SAP 檢查依賴圖;
Project 數量、資料夾名稱與架構名稱不得列為評分項目。
- Folder、Namespace、Project、Assembly 與 NuGet Package 必須分開說明;
`.csproj` 存在或 `dotnet pack` 成功,不得直接宣稱已符合 REP。
- Consumer 不得被迫依賴自己不用的 Entity、Framework、Provider、Policy 或 Public API;
若無關內容無法排除,回報 CRP 成本與較小邊界方案。
- Production ProjectReference/PackageReference Graph 必須標明分析範圍並保持無循環;
同時回報未涵蓋的 Runtime、Database、Configuration、Deployment 與 Team Coupling。
- 回報 `Ca`、`Ce`、`I` 或 `A` 時,必須標明分析單位、計算方式與 Consumer;
指標只作為設計審查時的警報,不得直接當作品質分數。
- 穩定元件只有在存在真實替換或擴充壓力時才新增抽象;
不得為提高 Abstractness 建立沒有 Consumer 的 Interface。
- 完成後回報元件內聚分析、實際依賴圖、Cycle Check、Consumer、Release 影響、
Build/Test、完整 Diff、未涵蓋的耦合與停止理由。
目前先用 AGENTS.md 格式示範,方便讀者直接套用。系列後段會再把這些 Policy 整理成 Skill,讓 Agent 依 Repository 情境載入需要的規則,不必把所有內容長期堆在全域說明裡。
回到標題,AI 很快就能把 API 拆成多個 Project,也能做出沒有循環的 Reference Graph。要判斷哪些邊界值得留下,還是得回到三個問題:誰真的會使用、什麼會因同一理由改變,以及這個單位是否真的需要獨立建置或發布。
現在只有 SLA 規則同時被 API 與 Reporter 使用,所以本系列只留下 WorkItems.ServiceLevel。這個選擇有共同變更、共同重用與依賴方向的證據;REP 仍缺正式版本與發布流程,SAP 也還沒有真實替換壓力,因此不提前增加 Package 或 Interface。
技術分層與功能元件仍有各自的適用情境。C — Context-Aware Code 情境感知 要我先看清 Consumer、Actor 與發布方式;L — Localized Change 局部變更 則要求每條邊界交代實際影響範圍。證據只支持一個共享元件,就先停在一個。
今天選出的元件圖,只回答目前已知需求。明天要進一步談持續設計:同樣三項需求,一次全部交給 AI,和依照需求真正出現的順序逐步加入,最後會形成一樣的抽象與修改成本嗎?我會再加入背景 Worker,觀察設計提前完成與持續演進之間的差異。