? ? ? 前面我們已經分析設計出了實體對象和對應的限界上下文,這兩個應該是可以同時設計出來的,如果只有領域和實體而沒有對應的限界上下文去管理,那么可以說這個設計就是未完成的。
? ? ? ?當然對于實體對象,在限界上下文中就有內部和外部之分,比如:訂單還和報表,庫存,物流(電商系統),對賬,結算(支付系統)等等相關,按照界限上下文的劃分,這些肯定不是一個上下文,但他們需要用到訂單對象,那么訂單這個實體對象對于上面這些限界上下文中就是外部實體對象。
針對外部實體對象,我們可以將其稱之為:值對象。可以看出來,值對象是一個相對的定義,即這個對象在其中一個上下文中,可能是領域對象,那么在其他上下文中則是值對象。而且對于被定義為值對象的限界上下文,值對象的屬性信息都基本上是不可變的(比如訂單對象,在做為值對象的時候,它的信息已經基本生成,而且基本可以不變)。而且上面每一個限界上下文中,訂單這個值對象的屬性的構成也是不一樣的,比如在對賬微服務中,我們只需關心這個訂單數據的金額以及其他訂單費用;而在結算系統中,我們更加關心的是訂單的狀態等信息,所以每一個限界上下文對于訂單的屬性構成也是不一樣的,不光不一樣,而且就訂單信息而言,這里的每一個限界上下文都只是需要訂單的信息,而不會去更改訂單的信息。所以在這些限界上下文中,這個訂單的數據就是值對象。值對象在這個限界上下文中是不變的。
? ? ? ?在限界上下文中,針對這種值對象的獲取方式,可以是調用遠程服務獲取,也可以通過緩存,事件傳遞,或則調用時的參數等等方式獲取。甚至對于值對象可以進行冗余似的存儲。
? ? ? 還有一種值對象,它天生就是不變的,即便是在它自己的限界上下文中,他也是值對象,因為他一旦產生就不會變了,比如一個日志信息,即便是日志系統產生了日志,但也是一產生就不再變化,所以日志對象在日志系統上下文中也是一個值對象。
? ? ? 總結一下:在某一個限界上下文中,我們會有這個上下文需要維護實體對象的信息,而不屬于這個限界上下文維護的實體對象則是值對象。在不同限界上下文中,會依賴的值對象的構成也是不同的,但不能超出這個值對象在做為領域對象的屬性。
? ? ? ? 所以值對象,一般是相對限界上下文來說的。但最重要的是請記住他的特點:不可變。
? ? ? ? 那么到了這一步,我們可以對整個系統通過設計分析,逐條劃分出哪些限界上下文有哪些是領域實體,依賴哪些值對象,可以慢慢的得出。
那么這么劃分領域實體和值對象有什么好處??
? ? ? 第一實體對象的邏輯處理是內聚的,比如上面說的訂單,那么訂單的一切變更邏輯都會聚合在訂單中心里(或交易中心里),那么對于維護這種邏輯,我們在工程上就會減少對應出錯的概率。
? ? ? 第二對于值對象,在一些場景下,微服務可以針對一些值對象進行緩存處理,這樣減少了服務依賴,增加了服務的健壯性,而且通過區分實體對象和值對象,我們也可以進一步發現流程梳理的漏洞(比如這個值對象從哪里來等等)。
? ? ? 第三,減少了對于數據庫依賴,特別是鎖的依賴。因為隨著實體的劃分清晰,大部分的事務處理集中在同一個微服務中,而服務間的依賴關系,更多的是通過不可變的值對象,不可變對象在多線程中是線程安全的,這樣減輕了部分事務鎖等待出現的概率。
最后通過上面的詳細梳理,大概能得到下面這個圖
這個圖中:圓圈代表實體,方塊代表值對象,箭頭代表創建關系。
可以看到,這個時候,我們的對象比之前表格中要更多,這是因為我們基于前一章表格的內容做了更多的細化。