# 🏛️ 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. **每季**: 架構演進規劃和調整 --- **記住**: 好的架構不是一蹴而就的,需要持續的關注和維護。這套治理體系將幫助您在功能增長的同時保持代碼品質!