6.5 KiB
6.5 KiB
🛡️ 架構防護檢查清單
📋 每次開發前必讀
🎯 功能開發前的架構決策
❓ 我要開發的功能屬於哪個領域?
📚 Learning (詞卡、學習、複習)
🤖 Analysis (AI分析、詞彙分析)
👤 User (用戶管理、認證、設定)
🔧 Infrastructure (快取、外部服務)
❓ 是否需要新的服務?
✅ 新業務領域 → 創建新服務
✅ 現有服務職責過重 → 拆分服務
❌ 只是小修改 → 擴展現有服務
❓ 服務應該放在哪一層?
🏢 Domain/: 核心業務邏輯
🔧 Infrastructure/: 技術實現
🤝 Shared/: 跨領域工具
✅ 代碼提交前檢查清單
🏗️ 架構規則檢查
服務設計
- 服務職責單一: 只做一件事,做好它
- 有介面定義: 每個服務都有對應的 I*Service 介面
- 命名清晰: 服務名稱表達業務意圖
- 大小適中: 服務文件 < 300 行(建議 < 200 行)
依賴關係
- 向上依賴: Domain → Infrastructure → Shared
- 無循環依賴: 服務間不相互依賴
- 介面隔離: 只依賴需要的介面方法
- 控制器分離: Controller 不直接調用 Repository
代碼品質
- 異常處理: 適當的 try-catch 和日誌記錄
- 參數驗證: 公共方法驗證參數
- 資源管理: using 語句管理 IDisposable
- 命名規範: 變數和方法名有意義
🚨 危險信號警報
❌ 立即停止的架構違規
🚨 Controller 直接使用 DbContext
→ 應該通過 Service 層
🚨 Domain Service 依賴 Infrastructure Service
→ 依賴方向錯誤
🚨 服務文件超過 500 行
→ 立即拆分
🚨 發現 "Manager"、"Helper"、"Utils" 類別
→ 重新設計為 Service
🚨 業務邏輯在 Controller 中
→ 移到對應的 Domain Service
⚠️ 需要注意的架構問題
⚠️ 方法超過 20 行
→ 考慮拆分為更小的方法
⚠️ 類別超過 10 個公共方法
→ 考慮是否職責過多
⚠️ 構造函數參數超過 5 個
→ 可能依賴過多,考慮重構
⚠️ 重複的錯誤處理代碼
→ 考慮建立統一的錯誤處理機制
🎯 快速自檢方法
1. 服務職責檢查
問自己:
1. 這個服務的職責能用一句話說清楚嗎?
2. 如果要給新人解釋這個服務,需要多長時間?
3. 這個服務是否混合了多個業務領域的邏輯?
✅ 好的例子:
"FlashcardService 負責詞卡的創建、更新和學習推薦"
❌ 壞的例子:
"UserFlashcardAnalysisService 負責用戶管理、詞卡操作、AI分析和快取管理"
2. 依賴關係檢查
快速檢查:
1. 打開服務文件,看 using 語句
2. 檢查構造函數參數
3. 確認沒有向下依賴
✅ 正確依賴:
FlashcardService 依賴 IFlashcardRepository
AnalysisService 依賴 ICacheService
❌ 錯誤依賴:
CacheService 依賴 FlashcardService
Repository 依賴 AnalysisService
3. 測試友好度檢查
問自己:
1. 這個服務容易寫單元測試嗎?
2. 所有依賴都是可以模擬的介面嗎?
3. 方法的輸入輸出是否清晰明確?
✅ 測試友好:
public async Task<FlashcardDto> CreateFlashcardAsync(CreateFlashcardRequest request)
❌ 測試困難:
public async Task DoComplexFlashcardOperation(object data, bool flag1, bool flag2)
📊 架構品質指標
🎯 目標指標
服務數量: 目標 8-15 個核心服務
平均服務大小: < 200 行
介面覆蓋率: > 90%
依賴深度: < 4 層
快取命中率: > 80%
📈 追蹤方式
# 快速檢查命令
echo "服務數量: $(find backend/DramaLing.Api/Services -name "*Service.cs" | wc -l)"
echo "介面數量: $(find backend/DramaLing.Api/Services -name "I*Service.cs" | wc -l)"
echo "平均文件大小: $(find backend/DramaLing.Api/Services -name "*.cs" -exec wc -l {} + | awk '{sum+=$1; count++} END {print int(sum/count)}')"
🔧 實用工具
架構決策模板
# 新功能架構決策
## 功能描述
簡述要實現的功能
## 架構選擇
- [ ] 使用現有服務
- [ ] 擴展現有服務
- [ ] 創建新服務
## 服務歸屬
- [ ] Domain/Learning
- [ ] Domain/Analysis
- [ ] Domain/User
- [ ] Infrastructure/*
## 依賴分析
列出需要依賴的其他服務,確認依賴方向正確
## 測試計劃
描述如何測試新功能
重構安全清單
# 重構前準備
- [ ] 現有功能有足夠測試覆蓋
- [ ] 識別所有受影響的代碼
- [ ] 準備回滾方案
# 重構中執行
- [ ] 小步驟,頻繁提交
- [ ] 每步都保持測試通過
- [ ] 保持 API 兼容性
# 重構後驗證
- [ ] 功能完全正常
- [ ] 性能沒有退化
- [ ] 文檔已更新
🎓 最佳實踐總結
👍 推薦做法
- 先設計介面,後實作: 確保 API 設計合理
- 小服務優於大服務: 職責單一,更容易維護
- 依賴注入: 所有依賴通過構造函數注入
- 異步優先: 所有 I/O 操作使用 async/await
- 日誌記錄: 關鍵操作要有適當日誌
👎 避免做法
- 靜態依賴: 避免 static 類別和方法
- 直接數據訪問: Controller 不直接操作數據庫
- 過度抽象: 不要為了抽象而抽象
- 忽略異常: 不要吞掉異常
- 魔法數字: 避免硬編碼的數值和字串
📞 獲得幫助
遇到架構問題時
- 查閱文檔: 先查看 ARCHITECTURE_GOVERNANCE.md
- 檢查現有模式: 看看類似功能是如何實現的
- 架構審查: 與團隊討論架構決策
- 逐步實施: 不確定時先小範圍實驗
常見問題 FAQ
Q: 我的服務變得很大,該怎麼辦?
A: 按職責拆分,一個服務只負責一個業務領域
Q: 我需要在服務間共享代碼,該怎麼辦?
A: 考慮建立 Shared 服務或抽取到基類
Q: 我的 Controller 邏輯很複雜,該怎麼辦?
A: 將業務邏輯移到對應的 Domain Service
Q: 我需要跨多個服務的操作,該怎麼辦?
A: 考慮建立協調服務或使用事件驅動模式
記住: 好的架構是團隊的共同責任,每個人都要參與維護!