Files
awoooi/docs/adr/ADR-014-dependency-governance.md
OG T 42659a271a docs(adr): ADR-014 Dependency Governance 依賴治理
建立前端依賴治理規範文件,.dependency-cruiser.cjs 已參照此 ADR。

內容包含:
- Layer Model 四層架構定義
- Feature Isolation 規則說明
- CI 整合配置 (pnpm dep-check)
- Severity 分級策略

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:12:43 +08:00

219 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-014: Dependency Governance
> **狀態**: 已採用
> **日期**: 2026-03-26
> **決策者**: CTO
## 背景
AWOOOI 前端專案 (`apps/web`) 隨著功能擴展,元件間的依賴關係日趨複雜:
1. **Feature 間相互引用**: agent/approval/incident/dashboard 元件互相 import導致修改一處牽動多處
2. **分層架構混亂**: ui 層引用 feature 層、hooks 引用 components違反單向依賴原則
3. **循環依賴**: A → B → C → A 造成難以追蹤的 bundle 問題
4. **缺乏自動化檢查**: 僅靠 Code Review 把關,容易遺漏
這些問題導致:
- 重構風險高,修改一個元件可能影響多個頁面
- 測試困難,無法隔離測試單一 feature
- 新人學習曲線陡峭
---
## 決策
採用 **dependency-cruiser** 工具,在 CI 階段自動檢查依賴規則。
---
## 理由
### 為什麼選 dependency-cruiser
1. **成熟穩定**: npm 週下載量 100K+,持續維護
2. **規則靈活**: 支援 regex、path match、severity 分級
3. **CI 友善**: 非零退出碼可阻擋違規 PR
4. **視覺化**: 可產出依賴圖 (dot/svg)
5. **TypeScript 原生支援**: 無需額外配置
### 考慮過的替代方案
| 方案 | 優點 | 缺點 |
|------|------|------|
| ESLint import/no-restricted-paths | 現有工具鏈 | 規則表達力有限 |
| NX enforce-module-boundaries | 強大 | 需導入 NX 生態系 |
| 手動 Code Review | 零成本 | 不可靠、不可擴展 |
---
## 技術實作
### 1. Layer Model (四層架構)
```
Layer 0: Pages (app/)
├── 可引用: 所有層
├── 職責: 路由、佈局、頁面組裝
Layer 1: Features (components/agent, approval, incident, dashboard)
├── 可引用: Layer 2, Layer 3
├── 禁止: 互相引用 (agent ↔ approval ↔ incident ↔ dashboard)
├── 職責: 業務邏輯封裝
Layer 2: Shared (components/shared, layout)
├── 可引用: Layer 3
├── 禁止: 引用 Layer 1 (下行依賴)
├── 職責: 跨 Feature 共用元件
Layer 3: Primitives (components/ui, lib/, stores/, hooks/)
├── 可引用: 僅外部套件
├── 禁止: 引用 components (保持純淨)
├── 職責: 基礎工具、原子元件
```
### 2. 依賴方向 (單向流動)
```
Pages (L0) → Features (L1) → Shared (L2) → Primitives (L3)
↓ 禁止 ↓ 禁止
互相引用 反向引用
```
### 3. Feature Isolation 規則
每個 Feature 為獨立模組,禁止橫向依賴:
```
❌ agent/xxx.tsx → import from 'approval/yyy'
❌ approval/xxx.tsx → import from 'incident/yyy'
❌ incident/xxx.tsx → import from 'dashboard/yyy'
✅ agent/xxx.tsx → import from 'shared/yyy'
✅ approval/xxx.tsx → import from 'ui/zzz'
```
### 4. 配置檔案 (.dependency-cruiser.cjs)
```javascript
module.exports = {
forbidden: [
// Feature Isolation (L1 禁止互相引用)
{
name: "feature-isolation-agent",
severity: "error",
from: { path: "apps/web/src/components/agent" },
to: { path: "apps/web/src/components/(approval|incident|dashboard)" }
},
// ... 其他 feature 同理
// Shared 禁止下行引用 (L2 → L1)
{
name: "shared-no-feature-import",
severity: "error",
from: { path: "apps/web/src/components/shared" },
to: { path: "apps/web/src/components/(agent|approval|incident|dashboard)" }
},
// Primitives 禁止引用 components (L3 保持純淨)
{
name: "hooks-no-component-import",
severity: "warn",
from: { path: "apps/web/src/hooks" },
to: { path: "apps/web/src/components" }
},
// 禁止循環依賴
{
name: "no-circular",
severity: "error",
from: {},
to: { circular: true }
},
// Components 禁止反向引用 app 層
{
name: "components-no-app-import",
severity: "error",
from: { path: "apps/web/src/components" },
to: { path: "apps/web/src/app" }
}
]
}
```
### 5. CI 整合
**package.json:**
```json
{
"scripts": {
"dep-check": "depcruise apps/web/src --config .dependency-cruiser.cjs"
}
}
```
**ci.yaml:**
```yaml
- name: Dependency Check
run: pnpm dep-check
```
### 6. Severity 分級
| Level | 行為 | 使用場景 |
|-------|------|---------|
| `error` | CI 失敗 | Feature Isolation、循環依賴 |
| `warn` | 輸出警告 | L3 引用 components (過渡期) |
| `info` | 僅紀錄 | 監控用 |
---
## 執行方式
### Phase 1: 啟用 (本週)
- [x] `.dependency-cruiser.cjs` 配置完成
- [x] `pnpm dep-check` script 加入
- [x] CI workflow 加入 dep-check step
- [x] ADR-014 文件建立
### Phase 2: 修復違規 (下週)
- [ ] 修復現有 Feature Isolation 違規
- [ ] 修復 Shared → Feature 違規
- [ ] 警告轉為錯誤 (hooks/stores/lib)
### Phase 3: 持續維護
- [ ] 新 PR 自動檢查
- [ ] 季度產出依賴圖供架構審查
---
## 後果
### 優點
- **架構可維護**: 依賴方向明確,修改影響範圍可預測
- **自動化檢查**: CI 阻擋違規,不再依賴人工 Review
- **Feature 可獨立開發**: 各 Feature 團隊可平行作業
- **測試隔離**: 可針對單一 Feature 進行單元測試
### 缺點
- **初期修復成本**: 需花時間修復現有違規
- **學習成本**: 開發者需理解 Layer Model
### 風險
- **過度嚴格**: 某些合理的跨 Feature 需求可能被誤擋
- **緩解**: 使用 `severity: warn` 過渡期,必要時新增白名單
---
## 參考
- [dependency-cruiser 官方文檔](https://github.com/sverweij/dependency-cruiser)
- [Clean Architecture - Dependency Rule](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
- [NX Module Boundaries](https://nx.dev/core-features/enforce-module-boundaries)