閒談軟體設計:Read Model

更新 發佈閱讀 6 分鐘
圖片來源:ChatGPT 生成

圖片來源:ChatGPT 生成

如果沒記錯,應該是在《CQRS 命令查詢職責分離模式》這本書第一次看到 Read Model 這個術語,但不確定是我讀的是翻譯本,還是原本就沒有,書中其實沒有對 Read Model 有明確的定義,就我的理解,導入 Read Model 有幾個目的:

  • 與領域模型分離,領域模型只處理複雜的關連與邏輯,避免負擔太多責任
  • 讀取模型能善用特定資料庫提供的功能最佳化效能

書中不少篇幅討論 DTO (Data Transfer Object) 與領域模型和讀取模型的關係,有趣的是,我對 DTO 的理解是從《Patterns Of Enterprise Application Architecture》這本書來的 (粗體是我認為重點的部分):

An object that carries data between processes in order to reduce the number of method calls.

本文中,DTO 就只是一個為了減少函式呼叫次數用來傳遞資訊的物件,和如今作為跨 boundary 傳遞資料的物件不太一樣。那今天到底要討論什麼?Read Model 還是 DTO?不急,先看怎麼使用,再來回顧究竟屬於什麼吧。

在一開始的架構設計之初,就把主管用的後台管理和員工使用的 app 各別提供一個後端 (Backend) [1],針對不同的應用提供專屬的 APIs,以目前的情況來說,後台管理使用的 APIs 操作的物件都比較接近領域模型,因為後台存在的目的就是用來管理這些複雜的領域模型。

圖片來源:ChatGPT 生成

圖片來源:ChatGPT 生成

後台操作介面需要的資料分成 metadata 和一般資料,後台操作介面也能編輯 metadata 和一般資料。提供一個物件將畫面所需要的資料都包起來,用一次 API 取得,聽起來好像不錯,但由於二者的更新頻率差異很大,這麼一大包資料的傳輸反而太花時間,由前端個別管理這些資料,只更新有變動的資料,再讓畫面根據變動更新即可,因此後台管理介面的後端幾乎沒有用到這類物件。

員工的 app 大多數時間只是檢視主管操作後的結果,雖然 metadata 仍可能因為主管編輯而變動,但資料卻是發布後員工才能看到的,在發布前任何操作的異動員工是無法得知,導致在員工端,metadata 和一般資料的更新頻率非常接近,這時一次 API 把畫面需要的資料全部取回反而是很划算的選擇。

這時候 Java 新的 record 真的幫上大忙,宣告 read-only 的大利器,這樣便宣告了一個 value object,還自動生成了 getter 和 equals 等函式:

ConnectedDailyNote 中,SimpleSquad 和 SimpleMerchant 都是對應 Squad 和 Merchant 的簡化版,只回傳了 app 需要的部分,app 不需要再次呼叫 API,只為了取得對應的內容。更重要的是,這些資料可以在 SQL statement 層級優化並取回,大大地提升效率。

上述的例子,還只是一個很簡單的例子,在實際系統中,有的資料結構由更多的簡化版 entity 組成,如果 app 都是各自取得這些資料,若不想頻繁呼叫 API,那可能要建立一個複雜的快取管理。透過這樣的資料結構,讓 app 取得即可呈現,某種程度簡化 app 的開發。

雖然導入這樣的資料結構不難,但使用上還是要注意一些細節:

  • 如果是 SQL 層級的優化,任何 schema 的改變都可能需要同時修改查詢條件,不然會造成查詢出現錯誤,因此一定要有單元測試,而且一定要使用相同 schema 測試 [2],不然會出現測試通過,但實際出錯的現象。
  • 如果是更複雜的資料結構,或是資料的背後是不同的系統,無法單靠一次查詢就組合出想要的資料結構,那就要思考如何優化查詢邏輯,減少查詢的次數。
  • 雖然 SQL 層級的優化可以加速,但某種程度上是可能打破模組的邊界,導致不是透過模組公開的介面讀取資料,這取捨得由團隊決定,只能透過公開介面讀取資料依然是個非常好的原則,個人的底線是,只能透過公開介面「修改」資料,其他唯讀操作視情況可以放行。

好啦!回到開頭討論的 Read Model 和 DTO,大家覺得 ConnectedDailyNote 是 Read Model 還是 DTO 呢?個人覺得是減少 API 呼叫次數且針對 SQL 優化的讀取模型,很貪心吧 (笑)!

可能有人會提到 GraphQL 也能做到類似的設計,沒錯,但本文討論的是一種設計的思維,透過把複雜的關聯維護邏輯 (Entity) 與讀取邏輯 (Read Model)分開,讓程式碼與資料結構以合理的方式分別維護,降低系統的複雜度,GraphQL 是一種實現的方式,但即便不用 GraphQL 也可以用這思維設計系統。

最後,留個小問題給大家,Read Model 在有使用 layer 或 clean architecutre 的系統中,應該放在哪一層?


  1. 這算是 Backend for Frontend 嗎?個人沒有這樣宣稱,當初的考量也不全是為了符合前端需求才分開。
  2. 這次專案使用 Testcontainers 真的是很方便,簡單的幾個 annotation 就可以在測試開始前準備好 PostgreSQL 的 container 進行測試,測試結束就把 container 消滅掉,讓測試和開發環境各自獨立。
留言
avatar-img
Spirit 異想世界
58會員
121內容數
這是從 Medium 開始的一個專題,主要是想用輕鬆閒談的方式,分享這幾年軟體開發的心得,原本比較侷限於軟體架構,但這幾年的文章不僅限於架構,也聊不少流程相關的心得,所以趁換平台,順勢換成閒談軟體設計。
Spirit 異想世界的其他內容
2025/12/21
分享瞭如何在新系統中應用樂觀鎖,透過 version 欄位簡化併發控制,同時保持高吞吐量。文章也觸及了樂觀鎖的進階應用及注意事項,並總結了兩種鎖機制的適用場景,為開發者提供實用的選擇指南。
Thumbnail
2025/12/21
分享瞭如何在新系統中應用樂觀鎖,透過 version 欄位簡化併發控制,同時保持高吞吐量。文章也觸及了樂觀鎖的進階應用及注意事項,並總結了兩種鎖機制的適用場景,為開發者提供實用的選擇指南。
Thumbnail
2025/12/14
現今的系統不論是 B to B、B to C 或是 B to B to C,通知都是不可少,不管是簡訊發送 OTP,還是發送臨時密碼的 email,或各式各樣的 push 通知,通知已不可少的環節,這也是為什麼在一開始系統架構設計時,早早把 ncc 規劃成一個獨立模組 (子系統)。
Thumbnail
2025/12/14
現今的系統不論是 B to B、B to C 或是 B to B to C,通知都是不可少,不管是簡訊發送 OTP,還是發送臨時密碼的 email,或各式各樣的 push 通知,通知已不可少的環節,這也是為什麼在一開始系統架構設計時,早早把 ncc 規劃成一個獨立模組 (子系統)。
Thumbnail
2025/12/13
本文深入探討了 UUID 的演進,介紹了 UUID v6 和 v7 相較於舊版本在時間排序上的顯著提升,以及 ULID 作為另一種優化 ID 設計的替代方案。技術是不斷進化的,定期檢視是必要的。
Thumbnail
2025/12/13
本文深入探討了 UUID 的演進,介紹了 UUID v6 和 v7 相較於舊版本在時間排序上的顯著提升,以及 ULID 作為另一種優化 ID 設計的替代方案。技術是不斷進化的,定期檢視是必要的。
Thumbnail
看更多
你可能也想看
Thumbnail
債券投資,不只是高資產族群的遊戲 在傳統的投資觀念中,海外債券(Overseas Bonds)常被貼上「高資產族群專屬」的標籤。過去動輒 1 萬甚至 10 萬美元的最低申購門檻,讓許多想尋求穩定配息的小資族望而卻步。 然而,在股市波動劇烈的環境下,尋求穩定的美元現金流與被動收入成為許多投資人
Thumbnail
債券投資,不只是高資產族群的遊戲 在傳統的投資觀念中,海外債券(Overseas Bonds)常被貼上「高資產族群專屬」的標籤。過去動輒 1 萬甚至 10 萬美元的最低申購門檻,讓許多想尋求穩定配息的小資族望而卻步。 然而,在股市波動劇烈的環境下,尋求穩定的美元現金流與被動收入成為許多投資人
Thumbnail
透過川普的近期債券交易揭露,探討債券作為資產配置中「穩定磐石」的重要性。文章分析降息對債券的潛在影響,以及股神巴菲特的操作策略。並介紹玉山證券「小額債」平臺,如何讓小資族也能低門檻參與海外債券市場,實現「低門檻、低波動、固定收益」的務實投資方式。
Thumbnail
透過川普的近期債券交易揭露,探討債券作為資產配置中「穩定磐石」的重要性。文章分析降息對債券的潛在影響,以及股神巴菲特的操作策略。並介紹玉山證券「小額債」平臺,如何讓小資族也能低門檻參與海外債券市場,實現「低門檻、低波動、固定收益」的務實投資方式。
Thumbnail
解析「債券」如何成為資產配置中的穩定錨,提供低風險高回報的投資選項。 藉由玉山證券的低門檻債券服務,投資者可輕鬆入手,平衡風險並穩定財務。
Thumbnail
解析「債券」如何成為資產配置中的穩定錨,提供低風險高回報的投資選項。 藉由玉山證券的低門檻債券服務,投資者可輕鬆入手,平衡風險並穩定財務。
Thumbnail
相較於波動較大的股票,債券能提供固定現金流,而玉山證券推出的小額債,更以1000 美元的低門檻,讓學生與新手也能參與全球優質企業債投資。玉山E-Trader平台即時報價、條件式篩選與清楚的交易流程等特色,大幅降低投資難度,對於希望分散風險、建立穩定現金流的人來說,玉山小額債是一個值得嘗試的理財起點。
Thumbnail
相較於波動較大的股票,債券能提供固定現金流,而玉山證券推出的小額債,更以1000 美元的低門檻,讓學生與新手也能參與全球優質企業債投資。玉山E-Trader平台即時報價、條件式篩選與清楚的交易流程等特色,大幅降低投資難度,對於希望分散風險、建立穩定現金流的人來說,玉山小額債是一個值得嘗試的理財起點。
Thumbnail
在現代產品開發中,工業設計與精密模型製作的緊密結合已成為成功的關鍵因素。IDMockup汐紫模型多年來致力於將創新的設計轉化為現實成品,並幫助客戶在產品設計和開發過程中解決各種挑戰。 工業設計是什麼 工業設計是一個多學科交叉的專業領域,專注於創建和開發以用戶為中心的產品。這些設計不僅需要
Thumbnail
在現代產品開發中,工業設計與精密模型製作的緊密結合已成為成功的關鍵因素。IDMockup汐紫模型多年來致力於將創新的設計轉化為現實成品,並幫助客戶在產品設計和開發過程中解決各種挑戰。 工業設計是什麼 工業設計是一個多學科交叉的專業領域,專注於創建和開發以用戶為中心的產品。這些設計不僅需要
Thumbnail
這篇文章介紹了面試時以及開始工作後可能會遇到的問題,包括物件導向OOP、SOLID 設計原則、測試方式,以及 Cookie、Session 與 Cache 的相似處與不同處。提供了豐富的相關資訊。
Thumbnail
這篇文章介紹了面試時以及開始工作後可能會遇到的問題,包括物件導向OOP、SOLID 設計原則、測試方式,以及 Cookie、Session 與 Cache 的相似處與不同處。提供了豐富的相關資訊。
Thumbnail
Selenium 是一個範圍廣泛的工具和函式庫的總稱專案,用於啟用和支援網頁瀏覽器的自動化。Selenium WebDriver 提供了 C#、JavaScript、Java、Python、Ruby 等多種語言的 API,可以用於編寫自動化測試軟體。 在定位元素時,WebDriver 提供對這 8
Thumbnail
Selenium 是一個範圍廣泛的工具和函式庫的總稱專案,用於啟用和支援網頁瀏覽器的自動化。Selenium WebDriver 提供了 C#、JavaScript、Java、Python、Ruby 等多種語言的 API,可以用於編寫自動化測試軟體。 在定位元素時,WebDriver 提供對這 8
Thumbnail
樣板模式的定義極為簡單,卻是大型系統程式、WEB/APP應用框架的設計核心,完美展現設計模式的價值: 簡單、高效、強大。
Thumbnail
樣板模式的定義極為簡單,卻是大型系統程式、WEB/APP應用框架的設計核心,完美展現設計模式的價值: 簡單、高效、強大。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News