最近完成了郵箱的功能。
郵箱的設計參考了mmzb的設計,基於一套msgsrv來實現。msgsrv是一個消息中轉的服務,這個服務是為了簡化玩家之間消息傳遞的過程。比如郵箱要向一個離線玩家發信,為了避免對離線玩家的數據進行修改,會通過msgsrv發送到玩家對應的msgbox里。玩家上線后,會自動查詢自己的msgsrv,檢索未讀消息。當玩家上線時,會主動在msgsrv中發起訂閱。每當有新的消息進入,msgsrv會直接發送到玩家所在的agent上,實現實時通知。唯一例外的情況,是全局消息的發送。一條全局消息發送的時候,只是向一個全局的隊列里插入一份數據。玩家只會在登錄時檢索一次這個全局隊列,並記住自己的檢索位置。缺點是全局消息的通知不及時,需要玩家離線再上線才能收到。需要實時的消息,可以通過聊天系統解決。
這個設計相對來說還是比較簡單的。但是,這個功能的提交,涉及到46個文件。我提交Pull Request的時候,自己都驚到了。當然,這其中並不是全部都是代碼的修改。這些修改可以簡單的分為三塊。一塊,是配置之類的修改,比如新增服務的參數,新增服務的數據存儲對應的數據庫定義,玩家數據庫對象新增的結構描述。這里占了7個文件。第二塊,是在lualib里提供的新api,為其他服務提供新功能的入口。其中還包含一些趁手的工具函數,方便以后功能的開發。這里占了8個文件。第三塊是大頭,實現了msgsrv的邏輯部分,以及郵箱的業務代碼。這一塊有31個文件,是這個PR的主要部分。
除了玩家自身的成長系統外,其他系統基本都涉及到兩部分。一部分,是掛在玩家的agent身上的,另一部分,則是對公有數據的修改。先看看agent的部分。agent身上需要有對應服務的api,供客戶端通過sproto協議來遠程調用。還需要有對應的api,供相應的skynet內服務的調用。一般還會有一套額外的gm api,供客戶端進行測試的時候使用。這三組api,功能覆蓋的面差不多,最終都會操作玩家身上的數據,通知到玩家的客戶端。就這次提交的郵件PR來看,這些api占住了7個文件。玩家數據部分的管理,是由幾個類完成的。這里占用了3個。總的來看,agent身上一共改了15個文件,稍微有點多。
剩下的文件,集中在對公有數據的修改上,即msgsrv的主體部分。其中有4個是用於執行功能測試的測試腳本,暫且不提。剝開msgsrv,首先是一層command,然后是對全局消息的管理器,對個人msgbox的管理器,對這兩者的管理器,以及管理msgsrv服務的啟動腳本、退出腳本、gm指令。這里的優化空間應該比較大,按照CRUD的四字法划分,個人消息管理器和全局消息管理器都有着多個“R”,多個“U”,正交性不夠好,還要錘煉一下。
優化現有的設計,主要目標是希望修改能夠更簡潔而清晰。不再因為添加一個小小的功能,就產生數十個文件的修改。對我來說,涉及的文件數量太多,就經常記不住細節,導致api改動的時候,常常出現漏改漏測。目前看到的可以優化的地方,就是各種自發現。比如lualib里面提供一個通用的調用api封裝,只要傳入方法名和服務名,就能自動調用對應服務的command api。數據結構的定義,能夠實現自動發現,不需要修改引用文件。(待續)