# 🏛️ DramaLing 架構治理指南
## 🎯 **架構治理目標**
> **核心原則**: 隨著功能增長保持架構清晰,避免技術債務積累
### **治理範圍**
- 🏗️ **架構邊界**: 服務、層次、模組邊界
- 🔗 **依賴管理**: 避免循環依賴和不當耦合
- 📏 **代碼標準**: 統一的編碼規範和模式
- 📊 **品質指標**: 可量化的架構健康度
---
## 🛡️ **架構防護措施**
### **1. 強制性架構規則**
#### **📁 目錄結構規則**
```bash
# ✅ 允許的依賴方向
Controllers → Services/Domain → Services/Infrastructure → Repositories → Data
# ❌ 禁止的依賴
Infrastructure → Domain # 基礎設施不能依賴業務邏輯
Repositories → Services # 數據層不能依賴服務層
Controllers → Repositories # 控制器不能直接訪問數據層
```
#### **🔧 服務命名約定**
```csharp
// ✅ 正確命名
public interface IFlashcardService // I + 業務名 + Service
public class FlashcardService // 業務名 + Service
// ❌ 錯誤命名
public class FlashcardManager // 避免 Manager
public class FlashcardHelper // 避免 Helper
public class FlashcardUtils // 避免 Utils
```
#### **🎯 單一職責驗證**
```csharp
// ✅ 職責清晰
public interface IFlashcardService
{
// 只處理詞卡相關業務邏輯
}
// ❌ 職責混雜
public interface IFlashcardAndUserService
{
// 混合多個業務領域
}
```
### **2. 自動化檢查工具**
#### **依賴分析腳本**
```bash
#!/bin/bash
# architecture-check.sh
echo "🔍 檢查架構規則..."
# 檢查循環依賴
echo "檢查循環依賴..."
find . -name "*.cs" -exec grep -l "using.*Services" {} \; | \
grep -E "(Repositories|Data)" && echo "❌ 發現不當依賴" || echo "✅ 依賴方向正確"
# 檢查過大的服務
echo "檢查服務大小..."
find Services -name "*.cs" -exec wc -l {} + | \
awk '$1 > 300 {print "⚠️ " $2 " 超過300行,考慮拆分"}'
# 檢查介面覆蓋率
echo "檢查介面覆蓋率..."
SERVICE_FILES=$(find Services -name "*Service.cs" | wc -l)
INTERFACE_FILES=$(find Services -name "I*Service.cs" | wc -l)
echo "服務介面覆蓋率: $INTERFACE_FILES/$SERVICE_FILES"
```
#### **架構測試**
```csharp
// Tests/Architecture/ArchitectureTests.cs
[Test]
public void Services_Should_Not_Depend_On_Repositories()
{
var assembly = typeof(Program).Assembly;
var serviceTypes = assembly.GetTypes()
.Where(t => t.Namespace?.Contains("Services") == true)
.Where(t => !t.Namespace?.Contains("Infrastructure") == true);
foreach (var serviceType in serviceTypes)
{
var dependencies = serviceType.GetConstructors()
.SelectMany(c => c.GetParameters())
.Select(p => p.ParameterType);
var hasBadDependency = dependencies.Any(d =>
d.Namespace?.Contains("Repositories") == true);
Assert.IsFalse(hasBadDependency,
$"Service {serviceType.Name} should not depend on Repository directly");
}
}
```
### **3. 代碼審查清單**
#### **每次 PR 必檢項目**
```markdown
## 🔍 架構審查清單
### 服務設計
- [ ] 服務職責單一且明確
- [ ] 有對應的介面定義
- [ ] 依賴注入正確使用
- [ ] 錯誤處理一致
### 依賴關係
- [ ] 無循環依賴
- [ ] 依賴方向正確 (向上依賴)
- [ ] 無跨層直接依賴
- [ ] 介面隔離原則
### 命名規範
- [ ] 服務命名遵循約定
- [ ] 方法名表達業務意圖
- [ ] 參數和返回類型合理
- [ ] 無魔法數字或字串
### 測試覆蓋
- [ ] 新服務有對應測試
- [ ] 核心業務邏輯有測試
- [ ] 異常情況有測試
- [ ] 測試名稱清晰
```
---
## 📊 **架構健康度指標**
### **可量化指標**
#### **1. 服務複雜度**
```bash
# 服務行數分佈 (理想範圍)
- 小型服務: < 100 行 (70%)
- 中型服務: 100-300 行 (25%)
- 大型服務: > 300 行 (5%)
```
#### **2. 依賴深度**
```bash
# 依賴鏈長度 (理想 < 4 層)
Controller → Service → Repository → DbContext
```
#### **3. 介面覆蓋率**
```bash
# 目標: 90%+ 服務有對應介面
介面覆蓋率 = (介面數量 / 服務數量) × 100%
```
#### **4. 測試覆蓋率**
```bash
# 服務層測試覆蓋率目標
- 單元測試: 80%+
- 集成測試: 60%+
- 端到端測試: 主要業務流程 100%
```
### **定期健康檢查**
#### **每週檢查項目**
```bash
# weekly-architecture-check.sh
#!/bin/bash
echo "📊 週架構健康檢查 - $(date)"
echo "=================================="
# 1. 代碼複雜度
echo "1. 代碼複雜度分析"
find Services -name "*.cs" -exec wc -l {} + | \
awk '{total+=$1; count++} END {print "平均服務大小:", int(total/count), "行"}'
# 2. 依賴關係檢查
echo "2. 依賴關係檢查"
./scripts/check-dependencies.sh
# 3. 測試覆蓋率
echo "3. 測試覆蓋率"
dotnet test --collect:"XPlat Code Coverage" --logger:console
# 4. 性能指標
echo "4. 快取效能檢查"
curl -s http://localhost:5008/api/ai/stats | jq '.data.cacheHitRate'
echo "=================================="
```
---
## 🔧 **實用工具和腳本**
### **1. 新服務創建模板**
#### **服務生成腳本**
```bash
#!/bin/bash
# create-service.sh
SERVICE_NAME=$1
DOMAIN=$2
if [ -z "$SERVICE_NAME" ] || [ -z "$DOMAIN" ]; then
echo "用法: ./create-service.sh FlashcardService Learning"
exit 1
fi
# 創建介面
cat > "Services/Domain/$DOMAIN/I${SERVICE_NAME}.cs" << EOF
namespace DramaLing.Api.Services.Domain.${DOMAIN};
///
/// ${SERVICE_NAME} 服務介面
///
public interface I${SERVICE_NAME}
{
// TODO: 定義業務方法
}
EOF
# 創建實作
cat > "Services/Domain/$DOMAIN/${SERVICE_NAME}.cs" << EOF
namespace DramaLing.Api.Services.Domain.${DOMAIN};
///
/// ${SERVICE_NAME} 服務實作
///
public class ${SERVICE_NAME} : I${SERVICE_NAME}
{
private readonly ILogger<${SERVICE_NAME}> _logger;
public ${SERVICE_NAME}(ILogger<${SERVICE_NAME}> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
// TODO: 實作業務方法
}
EOF
echo "✅ 服務 $SERVICE_NAME 已在 $DOMAIN 領域創建"
```
### **2. 依賴分析工具**
#### **依賴關係可視化**
```python
# dependency-analyzer.py
import os
import re
from graphviz import Digraph
def analyze_dependencies():
"""分析服務依賴關係並生成視覺化圖表"""
dependencies = {}
# 掃描所有 C# 文件
for root, dirs, files in os.walk("Services"):
for file in files:
if file.endswith(".cs"):
with open(os.path.join(root, file), 'r') as f:
content = f.read()
# 提取依賴關係
service_name = file.replace(".cs", "")
deps = re.findall(r'private readonly I(\w+Service)', content)
dependencies[service_name] = deps
# 生成依賴圖
dot = Digraph(comment='Service Dependencies')
for service, deps in dependencies.items():
dot.node(service)
for dep in deps:
dot.edge(service, dep)
dot.render('architecture/service-dependencies', format='png')
print("✅ 依賴關係圖已生成: architecture/service-dependencies.png")
if __name__ == "__main__":
analyze_dependencies()
```
### **3. 代碼品質守衛**
#### **Git Pre-commit Hook**
```bash
#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 執行架構檢查..."
# 檢查是否有 TODO 標記
if git diff --cached --name-only | xargs grep -l "TODO.*:" > /dev/null; then
echo "⚠️ 發現 TODO 標記,請確認是否應該完成"
git diff --cached --name-only | xargs grep -n "TODO.*:"
fi
# 檢查服務大小
LARGE_FILES=$(git diff --cached --name-only | grep "Service\.cs$" | xargs wc -l | awk '$1 > 300 {print $2}')
if [ ! -z "$LARGE_FILES" ]; then
echo "❌ 以下服務文件過大 (>300行),請考慮拆分:"
echo "$LARGE_FILES"
exit 1
fi
# 檢查命名規範
INVALID_NAMES=$(git diff --cached --name-only | grep -E "(Helper|Utils|Manager)\.cs$")
if [ ! -z "$INVALID_NAMES" ]; then
echo "❌ 發現不符規範的命名:"
echo "$INVALID_NAMES"
echo "建議使用 Service 後綴"
exit 1
fi
echo "✅ 架構檢查通過"
```
---
## 📚 **架構決策記錄 (ADR)**
### **ADR 模板**
```markdown
# ADR-001: 採用三層快取架構
## 狀態
已接受 (2025-09-23)
## 背景
需要降低 AI API 調用成本,提升響應速度
## 決策
採用三層快取架構:Memory → Distributed → Database
## 後果
- ✅ 大幅提升性能 (57,200倍)
- ✅ 降低運營成本 (67%)
- ⚠️ 增加系統複雜度
- ⚠️ 快取一致性需要管理
## 替代方案
1. 單層快取 - 性能提升有限
2. 只用分散式快取 - 需要額外基礎設施
```
### **重要決策記錄**
1. **ADR-001**: 三層快取架構
2. **ADR-002**: Repository Pattern 採用
3. **ADR-003**: 領域驅動服務設計
4. **ADR-004**: AI 提供商抽象層
---
## 🚦 **架構演進策略**
### **Phase 1: 穩定基礎 (當前)**
- ✅ 核心架構模式確立
- ✅ 服務邊界定義
- ✅ 快取系統整合
- 🔄 測試框架建立
### **Phase 2: 品質提升 (1-2週)**
```
目標:
- 80%+ 服務有介面
- 80%+ 測試覆蓋率
- 架構檢查自動化
- 依賴關係可視化
```
### **Phase 3: 監控和治理 (1個月)**
```
目標:
- 實時架構監控
- 技術債務追蹤
- 自動化品質閥門
- 性能基準監控
```
### **Phase 4: 微服務準備 (3個月)**
```
目標:
- 服務邊界驗證
- 通訊協定定義
- 數據一致性策略
- 部署自動化
```
---
## 🎯 **具體執行方案**
### **📅 每日實踐**
#### **開發者清單**
```markdown
開發新功能前:
- [ ] 確定功能屬於哪個領域 (Learning/Analysis/User)
- [ ] 檢查是否需要新服務或擴展現有服務
- [ ] 設計介面定義 (先介面後實作)
- [ ] 確認依賴關係符合架構原則
提交代碼前:
- [ ] 運行架構檢查腳本
- [ ] 確保新代碼有對應測試
- [ ] 檢查方法複雜度 (< 20行為佳)
- [ ] 驗證命名規範
```
#### **代碼審查要點**
```markdown
審查重點:
- 🎯 **業務邏輯位置**: 是否在正確的服務層?
- 🔗 **依賴方向**: 是否符合分層架構?
- 🧪 **可測試性**: 是否容易寫測試?
- 📏 **複雜度**: 方法是否過於複雜?
- 🏷️ **命名**: 是否表達清晰的業務意圖?
```
### **📊 品質看板**
#### **架構健康度儀表板**
```
🏗️ 架構健康度: 85% ↗️
📦 服務數量: 12 個
🎯 介面覆蓋率: 89% (目標: 90%)
🧪 測試覆蓋率: 73% (目標: 80%)
🔗 依賴違規: 0 個
📏 平均服務大小: 156 行 (良好)
⚠️ 需要關注:
- FlashcardController 過於複雜 (建議重構)
- AudioService 缺少單元測試
```
### **🚨 警報系統**
#### **架構違規警報**
```csharp
// 架構守衛:在 CI/CD 中執行
public class ArchitectureGuard
{
[Test]
public void Architecture_Should_Follow_Rules()
{
var violations = new List();
// 檢查服務大小
CheckServiceSize(violations);
// 檢查依賴方向
CheckDependencyDirection(violations);
// 檢查命名規範
CheckNamingConvention(violations);
if (violations.Any())
{
Assert.Fail("架構違規:\n" + string.Join("\n", violations));
}
}
}
```
---
## 🛠️ **重構安全指南**
### **安全重構步驟**
1. **📋 評估影響**: 列出受影響的組件
2. **🧪 增加測試**: 確保重構前有足夠測試覆蓋
3. **🔄 小步重構**: 每次只改變一個小部分
4. **✅ 驗證功能**: 每步都驗證功能正常
5. **📊 監控指標**: 確保性能沒有退化
### **重構檢查清單**
```markdown
重構前:
- [ ] 當前功能是否有測試覆蓋?
- [ ] 重構範圍是否定義清楚?
- [ ] 是否有回滾計劃?
重構中:
- [ ] 每個小步驟都能編譯通過?
- [ ] 測試是否持續通過?
- [ ] API 介面是否保持兼容?
重構後:
- [ ] 功能是否完全正常?
- [ ] 性能是否符合預期?
- [ ] 文檔是否更新?
```
---
## 📖 **最佳實踐總結**
### **🎯 核心原則**
1. **依賴倒置**: 依賴抽象,不依賴具體
2. **單一職責**: 每個服務只做一件事
3. **介面隔離**: 介面精簡,不強迫依賴不需要的方法
4. **開放封閉**: 對擴展開放,對修改封閉
### **🚀 實踐建議**
1. **先介面後實作**: 設計 API 時優先考慮介面
2. **小步快跑**: 頻繁提交小的改進,避免大重構
3. **測試先行**: 新功能先寫測試,後寫實作
4. **持續監控**: 定期檢查架構健康度
### **⚠️ 常見陷阱**
1. **過度抽象**: 不要為了抽象而抽象
2. **功能漏出**: 業務邏輯洩漏到控制器或基礎設施層
3. **依賴混亂**: 服務間循環依賴
4. **測試缺失**: 重構時沒有足夠的測試保護
---
## 🎓 **團隊執行指南**
### **新成員指導**
1. 📖 閱讀架構文檔
2. 🏗️ 理解分層原則
3. 🧪 學習測試模式
4. 🔧 熟悉開發工具
### **日常維護**
1. **每日**: 代碼審查關注架構原則
2. **每週**: 運行架構健康檢查
3. **每月**: 評估技術債務和重構需求
4. **每季**: 架構演進規劃和調整
---
**記住**: 好的架構不是一蹴而就的,需要持續的關注和維護。這套治理體系將幫助您在功能增長的同時保持代碼品質!