
圖片來源:ChatGPT 生成
在先前 閒談軟體設計:NCC 聊到,如何使用 ChannelProcessor 處理不同的通信意圖,並將意圖與實際的通訊手段分離,但有個核心的元素上回只是簡單地用 Message Queue 帶過,今天就來聊聊這個 Message Queue 的抽象層吧!
EventCenter 抽象層
跟載入 SMS SDK 只是為了滿足發送簡訊的意圖一樣,不管是使用 RabbitMQ 或是 GCP PubSub,其實也是完成發送一則事件或是訂閱一則事件的目的,實際上應用程式根本不在意是用 RabbitMQ 或是 GCP PubSub,這也是我個人不太喜歡在核心邏輯層與特定技術框架有關聯的主因。
要做到保護,最簡單的做法就是多一層抽象層:EventCenter,一個只有三個函式的介面,一個描述如何發送事件到某個主題 (topic),另一個描述如何建立一個訂閱並接收事件,最後,就是怎麼解除訂閱,這個抽象層很薄,基本上沒花什麼時間,是個值得的投入。具體實作
但只有抽象層是無法動的,要有具體的實作才能真正動起來,因此建立一個 GCPEventCenter 實作 EventCenter 這個介面。
在 publish 函式裡,setupPublisher 負責確保 GCP PubSub 的 topic 存在然後建立 publisher,最後將 event 轉成 GCP SDK 定義的 PubsubMessage 物件(asMessage) 發送出去。subscribe 則是反向的流程,setupScriber 會確保 subscription 存在,然後用 decoder 將 PubsubMessage 解碼回原本的型態,再派送給註冊的 listener。
GCP 的 SDK 提供的 API 其實蠻低階的,必須完成蠻多初始化的動作才能開始使用,這些過程,不論有沒有 EventCenter 這個抽象層,都是需要的,只是現在通通都集中在 GCPEventCenter 這個物件中,並統一用 EventCenter 這個介面操作。
如果哪天不想使用 GCP PubSub 了,想要自己架設 RabbitMQ 或是 Kafka 叢集,就新增一個 RabbitMQEventCenter 或是 KakfaEventCenter 然後實作相同的 EventCenter 介面。然後在原本注入 GCPEventCenter 的地方改成注入新的實作即可,核心邏輯層式不需要更改的。

NCC 與 EventCenter
回到 NCC,NCC 的 notify 實作其實很單純,只是將 intent 當作 event 送到對應的 topic,對於背後是 GCP PubSub 還是 RabbitMQ,是完全不知情的。
在接收端也是類似,若以布署的角度看 (下圖),在 Process A (傳送端),將 intent 送出,Process B (背景處裡端) 處理收到的 intent。

以架構或模組的概念看,NotificationCenter 和 DefaultNotificationCenter 則是放在核心模組 (ncc-core 模組),EventCenter 是核心模組能使用的介面,但在核心模組則看不到實作的類別 (PubSubEventCenter 在 gcp 模組)。
真正的實作實體,是應用程式啟動時,負責初始化後再將實體注入 (inject) 給 DefaultNotificationCenter,若要換另一個實作,只需在初始化時選擇另一個實作即可。

小節
到這邊,內容已經都講差不多了,EventCenter 作為一個抽象層,將意圖與實作分離,讓抽換時作能更將方便。不過,也許有人會問,EventCenter 對 NCC 來說,真的適合放在核心嗎?對於 NCC 來說,會不會也只是一個實作的細節?這其實是可以討論的,等之後有空再聊吧!
















