SDD-000 設計總覽與通用規範
| 項目 |
內容 |
| 文件編號 |
SDD-000 |
| 版本 |
1.0 |
| 狀態 |
已核定 |
| 撰寫者 |
SD |
| 審查者 |
SA / TL |
| 對應需求 |
全案設計之共通規範 |
1. 本文件之定位
SDD-001 ~ SDD-007 定義本系統之細部設計。本文件定義跨設計文件之共通規範:
分層職責、命名、通用模式、交易邊界、錯誤處理與擴充機制。
任一設計文件與本文件衝突者,以本文件為準。
| 文件 |
內容 |
| SDD-001 |
領域模型與 ER-Diagram(含可落地 DDL) |
| SDD-002 |
DFD 與流程分解 |
| SDD-003 |
Sequence Diagrams(關鍵情境) |
| SDD-004 |
Conflict Handling 與一致性設計 |
| SDD-005 |
狀態機設計 |
| SDD-006 |
API Contract(OpenAPI 3.1) |
| SDD-007 |
WebUI 設計規範 |
2. 分層職責
| 層 |
目錄 |
職責 |
可依賴 |
禁止 |
| 介面層 |
interfaces/ |
接收請求、驗證格式、轉換為命令、回應 |
application/、domain/
|
業務規則 |
| 應用層 |
application/ |
用例編排、交易邊界、埠呼叫 |
domain/ |
直接存取資料庫 |
| 領域層 |
domain/ |
業務規則、不變式、狀態轉換 |
僅標準函式庫 |
框架、ORM、HTTP、日誌 |
| 基礎層 |
infrastructure/ |
持久化、事件發布、外部適配 |
application/(埠)、domain/
|
業務規則 |
2.1 各層產出物對照
| 層 |
主要產出物 |
interfaces/ |
Controller、Request/Response DTO、Event Consumer、Mapper |
application/ |
UseCase(Command Handler)、Query Handler、Port 介面、DTO |
domain/ |
Aggregate、Entity、Value Object、Domain Service、Domain Event、Specification |
infrastructure/ |
Repository 實作、Outbox、Publisher、外部 Gateway、Migration |
3. 命名規範
| 元素 |
規範 |
範例 |
| 聚合根 |
業務名詞單數,PascalCase |
Authorization、CreditLimit
|
| 實體 |
單數,PascalCase |
AuthHold、SubAccount
|
| 值物件 |
單數,PascalCase;不可變
|
Money、CardNumber、LimitAmount
|
| 領域服務 |
動詞+名詞,PascalCase |
LimitCheckService、InterestCalculator
|
| 命令 |
祈使句+Command |
AuthorizeTransactionCommand |
| 查詢 |
名詞+Query |
GetAvailableLimitQuery |
| 事件 |
過去式+Event |
AuthorizationApprovedEvent |
| 用例 |
命令/查詢+Handler |
AuthorizeTransactionHandler |
| 埠 |
名詞+Port |
AuthorizationRepositoryPort |
| 適配器 |
技術+Adapter |
PostgresAuthorizationAdapter |
| 規格 |
名詞+Specification |
SpecialLimitApplicableSpecification |
| 錯誤碼 |
CC-<SVC>-<NNNN> |
CC-AUTH-1001 |
4. 通用設計模式
4.1 交易邊界(Unit of Work)
原則:一個用例 = 一個交易邊界 = 一個聚合的異動。
flowchart TD
A["用例開始"] --> B["開啟交易"]
B --> C["載入聚合"]
C --> D["執行領域行為"]
D --> E["驗證不變式"]
E --> F["持久化聚合"]
F --> G["寫入 Outbox 事件"]
G --> H["提交交易"]
H --> I["交易後發布事件"]
E -->|"不變式違反"| X["回滾並回報錯誤"]
F -->|"樂觀鎖衝突"| X
G --> X
規則
| 編號 |
規則 |
| TX-01 |
一個交易內僅異動一個聚合(跨聚合以事件最終一致) |
| TX-02 |
領域事件與聚合異動同一交易寫入 Outbox |
| TX-03 |
外部呼叫不得置於交易內(除必要之即時檢核,且須設逾時) |
| TX-04 |
交易內不得有長時間操作(批次、檔案) |
| TX-05 |
交易後才發布事件(避免事件早於資料提交) |
4.2 冪等(Idempotency)
flowchart TD
A["寫入請求"] --> B{"是否帶冪等鍵"}
B -->|"否"| E["拒絕:400 缺少冪等鍵"]
B -->|"是"| C{"冪等鍵是否已存在"}
C -->|"是,且請求指紋相同"| D["回傳前次結果(200/201)"]
C -->|"是,但指紋不同"| F["拒絕:409 冪等鍵衝突"]
C -->|"否"| G["執行業務邏輯"]
G --> H["寫入結果與冪等鍵(同一交易)"]
H --> I["回傳結果"]
| 規則 |
說明 |
| ID-01 |
所有寫入端點須帶 X-Idempotency-Key
|
| ID-02 |
冪等鍵保存期限 ≥ 24 小時(授權類 ≥ 14 天) |
| ID-03 |
同鍵同指紋 → 回傳前次結果,不重複執行 |
| ID-04 |
同鍵異指紋 → 409 衝突 |
| ID-05 |
業務層另有自然冪等鍵(如請款之 卡號+授權碼+日期+金額) |
4.3 樂觀鎖(Optimistic Locking)
| 規則 |
說明 |
| OL-01 |
所有可異動聚合含 version 欄位 |
| OL-02 |
更新條件含 WHERE id = ? AND version = ?
|
| OL-03 |
影響筆數為 0 → 拋出 ConcurrencyConflictError
|
| OL-04 |
授權熱路徑衝突採重試 3 次(指數退避),仍失敗則拒絕交易 |
| OL-05 |
額度扣減採條件更新(available >= amount)避免超額 |
4.4 Outbox(可靠事件發布)
| 規則 |
說明 |
| OB-01 |
事件寫入 outbox 表,與聚合異動同一交易 |
| OB-02 |
背景工作者輪詢未發布事件並發送至 Kafka |
| OB-03 |
發布成功後標記 published_at(不刪除,保留供稽核) |
| OB-04 |
消費者以 event_id 冪等 |
| OB-05 |
Outbox 表須有 (published_at, created_at) 索引 |
4.5 補償(Saga)
| 樣式 |
使用情境 |
實作 |
| 編排式(Orchestration) |
步驟少、需明確控制(如分期建立) |
由 Saga 協調者驅動 |
| 協同式(Choreography) |
步驟多、事件驅動(如帳務流程) |
各服務監聽事件自行反應 |
詳見 SDD-004 §4。
4.6 規格模式(Specification)
複雜業務條件(如授權檢核 13 大項)以規格物件組合,不得以 if-else 硬寫。
| 規則 |
說明 |
| SP-01 |
每個檢核項為一個 Specification 實作 |
| SP-02 |
檢核項之啟用與順序由參數決定 |
| SP-03 |
規格回傳「通過/不通過 + 原因碼」 |
| SP-04 |
規格須可獨立單元測試 |
4.7 領域事件
| 規則 |
說明 |
| DE-01 |
事件為過去式命名 |
| DE-02 |
事件含 aggregateId、sequenceNo、occurredAt
|
| DE-03 |
事件為不可變(immutable) |
| DE-04 |
事件僅包含下游需要之欄位(避免洩露內部結構) |
| DE-05 |
事件不得含個資明文(卡號須遮罩或 Token) |
5. 錯誤處理原則
| 原則 |
說明 |
| ER-01 |
領域層以例外表達不變式違反;例外須攜帶錯誤碼 |
| ER-02 |
應用層將例外轉為結果物件,介面層轉為 HTTP 回應 |
| ER-03 |
不得吞例外:catch 後必須重拋、記錄或補償(GOV-003 §6.1) |
| ER-04 |
錯誤訊息不得揭露內部實作細節 |
| ER-05 |
使用者訊息依 Accept-Language 本地化 |
| ER-06 |
每個錯誤碼須於 CSP-003 有對應說明與處理建議 |
5.1 例外階層
classDiagram
class DomainError {
+string code
+string message
}
class ValidationError
class BusinessRuleError
class ConcurrencyConflictError
class IdempotencyConflictError
class StateTransitionError
class ResourceNotFoundError
class ExternalSystemError
class InfrastructureError
DomainError <|-- ValidationError
DomainError <|-- BusinessRuleError
DomainError <|-- ConcurrencyConflictError
DomainError <|-- IdempotencyConflictError
DomainError <|-- StateTransitionError
DomainError <|-- ResourceNotFoundError
DomainError <|-- ExternalSystemError
DomainError <|-- InfrastructureError
| 例外 |
HTTP |
語意 |
ValidationError |
400 |
輸入格式錯誤 |
BusinessRuleError |
422 |
業務規則拒絕 |
ConcurrencyConflictError |
409 |
樂觀鎖衝突 |
IdempotencyConflictError |
409 |
冪等鍵衝突 |
StateTransitionError |
409 |
狀態機不允許之轉換 |
ResourceNotFoundError |
404 |
資源不存在 |
ExternalSystemError |
503 |
外部系統失敗 |
InfrastructureError |
500 |
基礎設施失敗 |
6. 擴充機制(客製化與自主開發)
對應 BRD-001 之客製化需求與 SYS-5/SYS-6。
| 擴充點 |
機制 |
說明 |
| 授權檢核規則 |
實作 Specification 並註冊 |
新增檢核項不需改核心 |
| 回饋規則 |
規則表 + 條件表達式 |
多維度組合由參數決定 |
| 手續費/利率 |
計價規則表 |
級距、比例、固定金額 |
| 報表 |
報表定義 + 樣板 |
新增報表不需改碼 |
| 通知樣板 |
樣板表 + 變數替換 |
多語系樣板 |
| 外部介接 |
實作 Gateway 埠 |
新增外部系統為新增適配器 |
| 狀態機 |
狀態與轉換表 |
新狀態為資料列 |
| 自訂欄位 |
擴充欄位表(UDF) |
本行可自行新增欄位 |
規則:擴充機制不得以修改核心程式碼為手段;核心程式碼不得含個別客戶之特例分支。
7. 設計文件之檢核
| 檢核項 |
標準 |
| 每個服務皆有分層結構 |
100% |
| 每個聚合皆有 ER 定義 |
100% |
| 每個關鍵情境皆有 Sequence |
見 SDD-003 清單 |
| 每個狀態機皆有轉換表 |
見 SDD-005 清單 |
| 每個端點皆有 API 契約 |
100% |
| 無反模式設計 |
0 筆(GOV-003 §6) |
| Mermaid 語法 |
0 錯誤 |