iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
Software Development

AI 時代的 Clean Code:30 天讓 AI 產出的程式碼可讀、可驗證、可維護系列 第 17

Day 17|AI 把 API 拆成多個 Project,怎麼判斷哪些元件邊界值得留下?

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

昨天整理完通知的行為契約、Consumer 需要的能力與原始碼依賴方向後,系列接續版本仍只有一個 Production Project。IWorkItemNotificationSender 由高階 Use Case 擁有,兩個通知 Adapter 反過來實作它。不過,所有 Production Code 仍編譯進同一個 Assembly,Build 還無法阻止不同責任之間出現不該有的參考。

看到這裡,我也很容易直接把程式碼拆成 DomainApplicationInfrastructureApi。建立 .csproj、搬移 Namespace、補上 Project Reference,再畫出一張箭頭朝內的依賴圖,對 AI Agent 來說並不困難。

九份候選跑完後,真正困難的果然不是做出無循環的圖,而是決定每個 Assembly 裡應該裝什麼。技術分層有一份候選讓只需要 SLA 的 Reporter 取得 Assignment Policy,因而被拒絕;功能元件三次都守住 Consumer 邊界,卻一次建立七個 Project;元件原則先行的三次結果,則都只抽出 API 與 Reporter 真正共用的 WorkItems.ServiceLevel

本系列最後接受原則先行 Run 02。不是因為 Project 最少一定最好,而是目前唯一能證明的共同重用內容只有 SLA 規則,而且這份候選還把 Reporter 案例放進一般測試流程。今天要回答的問題就是:每一條新增的元件邊界,究竟在保護哪一群 Consumer,又為什麼值得現在支付建置與發布成本?

〈元件原則〉把 Clean Code 從 Class 拉到可建置與發布的單位

前面談 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 沒有繞回原點,不能證明元件內部放對了東西。

Folder、Namespace、Project、Assembly 與 NuGet Package 提供不同層級的邊界

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。

Folder、Namespace、Project、Assembly 與 Package 的約束力與維護成本階梯

圖:元件邊界越強,維護成本也越高;只有真實變更壓力出現時,才需要往上一層升級。

加入只需要 SLA 規則的 Reporter,才能看出 Consumer 被迫依賴了什麼

如果實驗裡只有現有 API 這一個 Consumer,幾乎每一種 Project 拆法都能找到理由,很難觀察共享 Assembly 是否夾帶使用者根本不需要的內容。

因此,我刻意新增一個可獨立建置與執行的 WorkItems.ServiceLevelReporter Console Project。它是實驗工具,不是已上線產品,也不是正式背景程式需求。它只製造一個具體問題:第二個程式只想重用 SLA 規則時,會不會被迫一起依賴 Entity、資料庫與通知功能?

Reporter 依序接收 PriorityDueAtUtcCurrentUtc 三個參數,重用 API 既有的 ServiceLevelEscalationPolicy,最後只能輸出 EscalationRegular。主流程固定兩個案例:

  • High Priority,逾期 48 小時,輸出 Escalation
  • Normal Priority,逾期 12 小時,輸出 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 在今天真正要攔下的問題。

用 CLEAN 的 C 與 L 提供 Consumer 情境,並限制元件拆分範圍

C — Context-Aware Code 情境感知:元件邊界必須對得上 Consumer、Actor 與發布方式

C — Context-Aware Code 情境感知 要我先提供 Repository 目前真的存在的情境:兩個 Consumer 共同使用 SLA 規則;目前沒有不同功能團隊、獨立部署、Package 版本或多套 Domain Model。

這些尚未出現的需求同樣重要。只給 Agent 一句「請依 Clean Architecture 模組化」,它只能用常見架構補完空白;資料夾可以很漂亮,邊界卻不一定對得上這個 Repository。

L — Localized Change 局部變更:衡量一次改動會波及哪些建置、測試與 Consumer

L — Localized Change 局部變更 的檢查範圍超過檔案數。下一次 SLA 門檻改變時,我還要看哪些 Project 需要重新 Build、哪些測試要重跑、哪些 Consumer 得跟著升級。

Reporter 只需要 SLA,卻因一行門檻調整而被迫接受整套 Domain 或整個 API 的更新,修改範圍仍然過大。

這兩項原則決定了今天的操作方式:先把 Consumer 與禁止依賴寫清楚,再觀察不同邊界指令會把同一個 Agent 帶往哪裡。

用三種 Prompt 比較不同的 Project 邊界決策方式

三種案例使用相同起點、需求、模型、推理強度、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:

功能測試通過後,主流程還要檢查 Reporter 是否取得無關內容

九份候選都要由主流程重新驗證。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 的完整資料都保留在公開實驗結果。接下來看每種邊界實際保護了什麼。

技術分層能建立單向依賴,仍可能讓 Reporter 引用過大的 Domain

技術分層 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 還太大。

功能元件讓責任更容易辨識,也讓小型 API 一次多出七個 Project

功能元件候選拆得更細:

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 的啟動時序與對外行為不能跟著改變。

功能元件目前缺少相應發布壓力。NotificationsPersistenceOverdueProcessing 仍由同一個 API 組裝與發布,部分 Project 只有少數類別,卻都需要自己的 .csproj、Lock File、Reference 與 Build 節點。

若這些功能未來出現不同 Consumer、團隊、權限、版本或部署週期,我會重新考慮功能元件。現在直接留下七個 Project,成本已經出現,支持它們獨立發布的需求卻還沒出現。

元件原則先行只抽出 API 與 Reporter 共同使用的 ServiceLevel

原則先行的三個 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 使用 CaCeI 描述這件事:

Ca:有多少外部元件依賴它
Ce:它依賴多少外部元件
I = Ce / (Ca + Ce)

I 越接近 0,表示元件在目前依賴圖中越穩定;越接近 1,表示它主要依賴別人,自己比較容易改。

SAP 另外使用 A 觀察抽象程度:

A = 抽象類別數 / 類別總數

AI 可以放進 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 = 2Ce = 0I = 0。兩個較易變的執行程式共同依賴它。
SAP ServiceLevel 目前只有一個具體政策,呈現「穩定但具體」的質化警示;現階段沒有第二個實作或替換壓力,不增加空 Interface。

SAP 的警示值得留下,但我不會為了讓 A 變大就建立沒有 Consumer 的 Interface。抽象要保護真實替換或擴充壓力,多一個檔案不會讓 SLA 門檻更容易修改。

技術分層、功能元件與維持單一 Project 都有適用條件

原則先行只要求每條邊界提出證據,不會永遠得到最少 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

本系列接受第二次原則先行結果,因為 Reporter 行為能跟著一般測試持續重跑

目前已經出現第二個 Consumer,卻還沒有多個功能團隊、獨立發布或 Framework 隔離壓力。因此,只抽出 API 與 Reporter 共同使用的 SLA Assembly,比完整技術分層或七個功能元件更符合現況。

三份原則先行候選得到相同的 Production Graph。Run 02 額外把 Reporter 的兩個行為案例納入一般測試流程,所以未來每次執行 dotnet test 都會重新驗證 High/48 小時與 Normal/12 小時的結果。它沒有增加 Production Project,也沒有擴大 Reporter 的依賴。

因此我接受 Run 02。多出的測試程式碼不是免費的,但它能防止 SLA 規則與第二個 Consumer 在後續修改中悄悄分岔,這筆成本有明確用途。

本系列接下來沿用:

  • Commit:76de5b546bd07179676423cb7e336ba20add2f95
  • 正式候選 Tag:day-17-formal-principles-first-boundary-run-02
  • 系列接續 Tag:day-17-component-principles

讀者可以切到實驗起點:

git switch --detach day-17-component-principles-baseline

再切換到系列接續版本:

git switch --detach day-17-component-principles

也可以直接查看 Baseline 與系列接續版本的完整 Diff

原則先行候選的 Diff 與 Fresh Input 較小,Tool Calls 沒有跟著下降

三種方向各跑三個 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 適合比較通過相近品質門檻後的執行成本,不能拿來替六項元件原則打分數。

把不同專案情境都寫進 Component Boundary Policy

前面幾篇已經示範過 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 情境載入需要的規則,不必把所有內容長期堆在全域說明裡。

目前只留下 WorkItems.ServiceLevel,其他邊界等需求出現再拆

回到標題,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,觀察設計提前完成與持續演進之間的差異。

參考資料


上一篇
Day 16|兩個通知 Provider 都能編譯,為什麼還不能證明可以互相替換?
下一篇
Day 18|AI 一次完成三項需求,和逐步設計相比,加入背景 Worker 時有什麼差別?
系列文
AI 時代的 Clean Code:30 天讓 AI 產出的程式碼可讀、可驗證、可維護23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言