Community程式設計與開發github.com

yutna/oo-design

適用於在物件導向程式碼庫中開始新模組、功能或系統、評估設計規模,或不確定該採用哪條物件規則時使用。

oo-design 是什麼?

這是一套專為物件導向程式碼庫提供的設計規則,並非通用建議。它會根據任務規模推薦適合的技能,並強調專案自身的慣例優先於此套件。技能內容涵蓋了從設計前的守門規則、設計迴圈的七個步驟,到各種症狀對應的處理技能,以及語言特定技能(如 Java、Kotlin、TypeScript),幫助開發者決定設計的深度。此外,它還定義了規則的嚴格程度(規則、預設、判斷),讓開發者能精準應用。此技能支援各種 AI 編碼代理,例如 Claude Code、Cursor 和 Codex。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/yutna/object-oriented-design-skills/tree/HEAD/plugins/core/skills/oo-design

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

物件導向設計

概覽

這套規則專為採用物件導向風格的程式碼庫而設計,並非通用建議。專案自身的書面慣例優先於此套件。請遵循正在修改的模組的慣用語法。此技能會評估任務規模並命名適合的技能。

在回答之前,請先載入此索引所命名的技能:其規則與範例存在於該技能中,而非此處。

任務需要多少設計

任務使用跳過
只使用一次即捨棄的答案無所有
現有類別中的一個方法其名稱與合約重新建模
現有流程內的一個功能該流程使用的慣用語新邊界
一個新的類別或模組設計迴圈無
一個新的上下文 (Context)設計迴圈,然後是其邊界無
從無到有的新系統設計迴圈、上下文,然後是結構無

在設計之前

在設計之前,先陳述守門規則:軟體必須遵守的一條規則,並提供一個它接受和一個它拒絕的範例。例如:「一個時段最多只能容納一個預約。」它接受將第二位病人預約到另一個時段,並拒絕將第二位病人預約到同一個時段。如果你能將規則寫下來,就開始設計。如果你做不到,那麼缺少的就不是設計,而這套技能也無法提供。

設計迴圈

  1. 用領域的語言來說明軟體必須做什麼 (說領域語言), 並找出知道每個行為需要什麼的物件 (分配責任)。
  2. 找出一致性邊界:哪些事物必須在同一個交易中保持一致 (設計聚合)。
  3. 決定每一條規則的位置:實體 (Entity)、值物件 (Value Object),還是領域服務 (Domain Service) (放置領域邏輯)。
  4. 設計每個物件應答的訊息 (封裝狀態與行為), 並使非法狀態無法被建構 (使非法狀態無法存在)。
  5. 反轉依賴,使領域層不認識資料庫或框架 (反轉依賴, 分層系統)。
  6. 使用領域的語言來命名事物,並僅註解程式碼無法表達的內容 (命名類別與方法, 註解程式碼無法表達的內容)。
  7. 根據下方的紅旗警訊檢查結果 (審查物件設計)。

規則的嚴格程度

此套件中的每一條核心規則都帶有三個標籤之一,標籤說明了其嚴格程度。

  • 規則 (Rule)。 違反即為缺陷。沒有框架可以豁免。
  • 預設 (Default)。 除非有明確的條件成立,否則請執行此操作。條件本身就是一個句子,絕不是附加子句。
  • 判斷 (Judgement)。 兩種答案都是可辯護的。技能會說明是什麼因素打破了平衡。

症狀對應技能

症狀指向處理它們的技能,此表格會隨著技能的增加而增長。

症狀技能
哪個類別應該做這件事?分配責任
這個類別做太多事了分配責任
一個變更波及許多類別診斷耦合
這兩個部分的耦合程度如何?診斷耦合
這是物件還是單純的資料?決定物件或資料
我們的領域模型是貧血的決定物件或資料
其他程式碼替這個物件做決定封裝狀態與行為
Setter 讓此物件可以違反其規則封裝狀態與行為
此物件可以半成品狀態存在建構有效的物件
這個建構函數需要太多引數建構有效的物件
每個新案例都意味著編輯運作中的程式碼封裝會變動的部分
這個功能應該有多少彈性?封裝會變動的部分
這是值物件還是實體?建模值與實體
原始字串和數字攜帶了領域規則建模值與實體
這個類別應該繼承那個類別,還是持有它?選擇組合勝過繼承
變更基底類別會破壞其子類別選擇組合勝過繼承
子類別違反了其父類別承諾的內容尊重可替代性
程式碼檢查它持有哪個子類型尊重可替代性
同一種型別的 switch 判斷一再出現用多型取代條件式
子類別還是模式匹配?用多型取代條件式
程式碼穿過一串物件鏈限制物件的所知範圍
這個類別只轉發呼叫限制物件的所知範圍
這個類別或方法應該叫什麼?命名類別與方法
像 Manager、Helper 或 Util 的名稱命名類別與方法
呼叫者依賴於它們從未使用的介面方法設計介面
介面還是抽象基底類別?設計介面
領域程式碼依賴於資料庫或框架反轉依賴
物件在哪裡被建立和組裝?反轉依賴
呼叫者知道另一個類別如何儲存或格式化資料隱藏實作
一個類別洩漏了其內部錯誤或步驟隱藏實作
標記或可選欄位允許不可能的組合使非法狀態無法存在
一個型別允許領域中從不曾有的值使非法狀態無法存在
程式碼的用詞與團隊的用詞不同說領域語言
一個詞對兩個團隊代表不同意義說領域語言
哪些物件必須一起變更?設計聚合
儲存時發生衝突,或一次載入拉進太多東西設計聚合
哪些狀態變更是允許的?建模生命週期
一個已取消或已關閉的物件再次發生變更建模生命週期
領域物件應該如何被儲存和尋找?設計儲存庫
儲存庫有一個針對每個畫面的 find 方法設計儲存庫
使用案例重複執行相同的商業檢查放置領域邏輯
領域服務、實體方法還是應用服務?放置領域邏輯
其他部分必須在變更儲存後做出反應發布領域事件
針對一個已回滾的變更發出了訊息發布領域事件
一個團隊的模型在哪裡結束,另一個的在哪裡開始?界定上下文
哪些部分是核心,哪些我們可以購買?界定上下文
各層應該朝哪個方向依賴?分層系統
一個畫面或作業無法在沒有其框架的情況下進行測試分層系統
模組之間形成循環依賴組織模組
模組化單體還是獨立服務?組織模組
對我們 API 的變更破壞了呼叫它的應用程式跨越系統邊界
我們該如何對這個 API 或訊息進行版本控制?跨越系統邊界
映射工具塑造了我們的領域類別馴服持續性
一個列表對每一行執行一次查詢馴服持續性
畫面需要的資料形狀與模型不同分離讀取與寫入
讀取模型、投影還是事件溯源?分離讀取與寫入
這個畫面該用 MVC、MVP 還是 MVVM?分離呈現層與領域層
一個畫面直接編輯領域物件分離呈現層與領域層
哪個設計模式適合這個問題?選擇模式
在問題出現之前就加入了模式選擇模式
這些模式類別可能只是一個函式語言提供的模式
Visitor,還是帶有匹配的封閉集合?語言提供的模式
一個方法在找不到東西時回傳 null設計失敗行為
拒絕以呼叫者忽略的錯誤碼形式回傳設計失敗行為
執行緒共享一個物件,遺失或混淆了其變更管理共享狀態
對此狀態使用鎖還是單一持有者?管理共享狀態
對另一個系統的呼叫掛起或執行到一半失敗使工作可靠
重試導致工作被執行了兩次使工作可靠
我們無法根據記錄解釋事件設計要記錄的內容
我們應該記錄、計數或稽核什麼?設計要記錄的內容
審查發現一個神級類別或熔岩流辨識反模式
我們應該先修正哪個反模式?辨識反模式
測試雖然行為沒有改變卻失敗了測試物件導向程式碼
對此協作者使用 Mock、Stub 還是 Fake?測試物件導向程式碼
測試依賴於時間或隨機值設計可測試性
程式碼僅為了測試可以存取而被設為公開設計可測試性
我們如何安全地重構這份程式碼?重構朝向物件設計
重構變得太大而無法完成重構朝向物件設計
我們必須變更沒有測試的程式碼處理舊有程式碼
逐步取代舊系統處理舊有程式碼
這次審查應該檢查什麼?審查物件設計
哪些審查發現會阻止合併?審查物件設計
沒有人記得為什麼程式碼會是這個形狀記錄設計決策
我們應該畫什麼,以及在什麼層級?記錄設計決策
註解重複了程式碼或與之矛盾註解程式碼無法表達的內容
我們在哪裡解釋為什麼這段程式碼看起來很奇怪?註解程式碼無法表達的內容
一個框架鉤子或標記持有商業規則在框架內工作
我們應該在多大程度上順應框架?在框架內工作
一個計算也儲存、發送或改變了它的輸入應用函數式技巧
哪些函數式技巧適合物件程式碼?應用函數式技巧

語言技能

語言技能將核心規則保留在一個語言中,絕不取代它們。基礎語言技能適用於沒有框架的程式碼。

  • oo-java,來自 object-oriented-design-java:記錄 (records)、密封類型 (sealed types)、equals 和 hashCode、受檢例外 (checked exceptions)、Optional,以及禁止擴展的類別。
  • oo-kotlin,來自 object-oriented-design-kotlin:資料類別 (data classes)、密封類型 (sealed types)、可空類型 (nullable types)、使用 by 的委派 (delegation),以及擴展函式 (extension functions)。
  • oo-typescript,來自 object-oriented-design-typescript:品牌識別字 (branded identifiers)、#private 狀態、抽象類別 (abstract classes)、裝飾器 (decorators)、差別聯合 (discriminated unions),以及組合根 (composition root)。
  • oo-javascript,來自 object-oriented-design-javascript:c

…

[因篇幅限制而截斷]

相關技能