Activity Framework GameDataProvider Constructor Injection¶
概念概覽
根本問題¶
核心知識¶
根本問題¶
Activity 模組錯誤引用了 architecture.md §4.6 的「circular dependency 例外」,使用 post-init setter(SetScheduleConfigLoader、SetFleetRegistry)。但 ActivityService 根本不存在 circular dependency,§4.6 例外不適用。
正確的標準模式¶
所有其他模組(player、dungeon、teach、sticker)都走同一條路:
configManager = config.NewManager(cfg.ConfigDir, ...)
var gameData player.GameDataProvider = configManager
playerDeps = player.InitializePlayer(..., gameData)
config.Manager 實作 GameDataProvider 介面,Wire 建構期注入,各模組從 gameData.GetGameData().Tables_Xxx 直接讀 Luban 表。
修正策略¶
- 刪除
ScheduleConfigLoaderinterface、SetScheduleConfigLoadersetter、configLoadermutable 欄位 - Activity 模組定義自己的
GameDataProviderinterface(與 sticker 相同模式,避免 import player) InitializeActivity加gameData GameDataProvider參數main.go把現有configManager傳入,零新抽象ActivityScheduleConfigLuban 表尚未存在(#29 PD 外部工作),PD 交表跑 codegen 後即可直接讀,不需要任何中間 loader
Silent Fail-Open 修正¶
checkFleetConvergence 和 getFleetBundleStatus 的 nil-bypass 是同一個根因的延伸:
// 錯誤:if s.fleetRegistry == nil { return nil } // 靜默放行
// 正確:FleetRegistry 透過 Wire constructor injection 後永遠非 nil
Wire 建構期注入後,nil guard 可完全刪除。
經驗教訓¶
-
architecture.md §4.6 的 post-init setter 例外僅限於真實 circular dependency,不可套用於任何其他情境
-
新模組抽象(ScheduleConfigLoader)在既有通用機制(GameDataProvider)能覆蓋時是技術債,應刪除而非修補
-
Luban 表尚未存在(PD 外部工作 pending)不是發明新 interface 的理由,機制先到位,表後補即可
常見陷阱¶
-
誤用 circular dependency 例外為 setter pattern 的藉口
-
setter 欄位不被 Wire 追蹤,編譯期不報錯但 runtime nil dereference 或靜默 fail-open
-
自製 loader interface 複製既有 config.Manager 功能,造成兩套機制並存
最佳實踐¶
-
每個模組都定義自己的 GameDataProvider interface(structural typing),避免跨模組 import
-
Wire 建構期注入消除 nil-bypass guard 的必要性,讓 nil dereference 在啟動時即時崩潰而非靜默放行
-
加新模組前先 grep 確認既有通用機制是否已覆蓋需求
相關概念¶
- gamedataprovider-pattern----dangling-------dangling---
- go-wire-dependency-injection----dangling-------dangling---
- golang-migrate Version Collision Fix
- luban-codegen----dangling-------dangling---
- Twirp Admin RPC Audit Architecture
相關視角¶
以下頁面與本概念共享主題,但從不同角度切入。保留獨立視角同時提供交叉參考:
- Reward Claims Architecture — 共享:
game-server/ 獨特:reward-system,schema-design - Activity Framework Settlement Idempotency — 共享:
activity-framework/ 獨特:idempotency,settlement - Redis Sorted-Set TTL GC Capacity Bomb — 共享:
game-server/ 獨特:capacity-planning,event-system
來源 Sessions¶
| 日期 | Session | 貢獻摘要 |
|---|---|---|
| 2026-04-10 | a7f313c0-2db2-4e32-8dc4-43117b1a66b8 | 發現 Activity 模組是唯一沒走 GameDataProvider constructor injection 的模組,刪除 ScheduleConfigLoader 自製 interface 並統一走 Wire 標準路線 |