前言
這篇稍微紀錄一下這次讀本書第五篇的感想,這篇前面再講很重要的 ubiquitous Language (統一語言)跟 Bounded Contexts (綁定上下文)。但我想記錄其中的 Context Mapping(上下文映射) 跟 The Layered Architecture (分層架構篇)
Agenda
- Context Mapping(上下文映射)
- The Layered Architecture (分層架構篇)
前提
- 這篇算是進入領域模式的開章,綁定上下文沒有一套完美的走法來告訴你如何實現,界定上下文的邊界取決於你的商業模型,時間,人力甚至技能。但這裡有兩個我一直搞混的東西,那就是在架構上,常常把硬體的架構跟軟體的架構混在一起,其實也是因為我們對整體 ubiquitous Language 沒有定義好才導致的,因為在公司內部要有人懂這塊基本上太難,有幸遇到說不定當時我也聽不懂,直到慢慢的累積學習到的經驗,開始發現本書內的某些解釋都可以呼應到以前遇到的種種問題,這時候才真的覺得原來如此,有時候太早看到此書也沒用,因為本身的能力的體驗還不到那階段。回到本篇文章,不管是在做專案還是討論任何的議題,統一語言是非常重要的,這可以大大節省成本。很多搞混也是語言上的模糊不清才導致後續的不明白。回到我剛剛說的問題,在硬體架構我們要說Tier。在軟體架構我們要說Layer,而常常我們把這兩個混在一起了。DDD裡的 Strategic Model Design 策略模型設計 階段就是來評估架構方案的,還有就是每個綁定上下文所適合的架構,聽到這裡大家應該是點點頭。看看下面Bounded Contexts範例如何。
Bounded Contexts
具體一點,一個購物網站,他會有的專案不會只有B2C,他還會有B2B,B2E,Job等等專案,甚至一些內部專案。這些整體來看都屬於DDD的規範(硬軟體)。當你劃分好上下文跟上下文邊界後,你就可以設計每個上下文的合適架構。每個喔,可以是不一樣的。B2C以現在流行的方式可以是SPA + WebAPI。B2B可以是ASP.NET MVC,以此類推。如果遇到需要共用的上下文,例如會員,剛好有兩個前台B2C網站或是手機網站或是APP程式,會員在這裡就可以有不同的劃分。我的作法會建立一組可共用的會員驗證Server,也就是一個專門發放Token的服務,使用JWT機制架上Refresh Token方式。有點像是Google或是Facebook的OWIN。在重疊的上下文方面,本文有其介紹:
- 在重疊的會員可以劃分成一整個上下文,B2C的兩個網站全部包再一起整個上下文,整個包含在內。
- 如果會員就希望是可以共用的也可以劃分B2C-1,B2C-2,共享內核(會員)。(我使用這個方式)
- 最後的方式還可以劃分每個前台網站有自己的會員,上下文都有自己的會員。
最終取決在於你當下的環境,沒有對錯。
附上一張本文的重疊 Resolving the conceptual overlapping of contexts.
- 以上是本文三種方式介紹,你說還會不會有其他的方式,我相信是有的。
Context Mapping(上下文映射)
這裡要講一個整體的大圖,做任何事情前,第一件事就是有明確目標,然後有一個大圖願景,讓你可以清楚知道整體範圍。在DDD裡面定義了一些 Relational Pattern 關係模式 ,這個模式定義了上下文之間的關係,使用 Upstream Context 跟 Downstream Context來標示上下文關係。以下是關係模式:
- Anti Corruption Layer 防腐層 : 通常使用在對接外部單位,由於不讓upstram Contexts異動而影響到downstream Contexts,防堵方式就是ACL,透過這層我們可以盡可能讓上文的異動不引響了下文的Contexts
- Conformist 從屬 : 屬於ACL的輕量級模式,下游的context會被動地接受上游的context模式,下游會接受包含他用不到的數據。
- Client/Server 客戶跟供應商 : 這在以前做物流範例很常用到,供應商只會給客戶他需要的數據資料,這是跟Conformist模式的最大差異。
- Partnership 搭擋 : 兩個上下文是分開的,不共享程式碼,但兩個上下文同時是對方的上下游,互相依賴。
- Shared kernel 共享內核 : 就是兩個上下文會去共享使用這個子model。耦合相對高。
附上一張本書內的上下文映射 A sample context map showing some of the DDD relational patterns.
The Layered Architecture (分層架構篇)
我以前一直搞混DDD的架構跟分層架構,感覺可以混在一起,但又有些不同,其實他是不一樣的,如果沒釐清界線很容易就搞混,討論起來就很模糊,DDD是一種架構設計,他的範圍比較大,還可以細分到使用其他的架構模式。記得每個上下文都可以有自己的架構。B2C專案不一定使用ASP.NET MVC。可以是.NET Core。這裡介紹支持的架構,但我先列出他們,因為有些內容尚未搞清楚,寫出來怕誤人子弟,而且每個架構都可以大篇幅的在探討,在這裡就不細講了。
- Multilayer architecture
- Multitier architecture
- Client/server architecture
- Domain Model
- Command-Query Responsibility Segregation (CQRS)
- Event sourcing
- Monolithic architecture
- Micro-Service
這裡我想記錄的是一個我以前搞混的狀況,需要說到以前我們使用的三層式架構,我們會把class區分成Presentation Layer,Business Logic Layer,Data Access Layerc。這也就是架構,不然你都寫一起就產了。但這是軟體的方式,硬體呢? 你會開一台IIS跟一台DB Server,還有AP。靠就是這AP搞死我的。以前我剛聽到的時候我就覺得怪怪,我不明白這是軟體架構還是硬體架構,還是整體架構。直到現在還是有人這樣搞混。其實AP server是指應用程式伺服器,阿裡面是啥,阿不就是IIS。所以就是再說Tier阿,那不就是硬體架構。你Google看看還可以看到很多網站介紹這是軟體架構。當然如果你什麼東西都只放在一台機器那就比較難區分了。Infra會說AP Server,DB Server,File Server,Log Server。多半都是再說硬體位置。而已前寫軟體的MIS都比較資深,所以RD常常會被拉著鼻子走,因為根本沒有架構師這號人物。如果你把邏輯層的架構部屬到物理層的架構上,你的服務就會有延遲,因為網路是有頻寬的,以前聽到作專案,在討論架構期間,常常會有這種哪裡怪怪的,就是因為物理架構(Tier)跟邏輯架構(Layer)搞混了。那現在呢? 看本文推薦:
那本文推薦的現代版架構是:
- Presentation Layer:
- Vue,Razor Page,React,Angular
- Application Layer:
- Controller
- Domain Layer:
- Model,Service 邏輯部分
- Infrastructure Layer
- Ioc,Cache,Repository
附上一張本文的架構圖 A more modern version of a layered architecture.
順道奉上我目前擅長的架構方式:
Layer:
- Presentation Layer:
- Vue
- Application Layer:
- Web API Controller,IoC
- Domain Layer:
- Model,Service 邏輯部分
- Utility (Cross Cutting) 這層跟Infra有類似
- Cache,Dapper,ADO.Net,Logger,
- DAL Layer 這邊一直是我沒符合DDD的原因
- Repository
Tier:
- AP Server (Member)
- AP Server (B2C主要的邏輯網站)
- AP Server (B2B)
- AP Server (內部維運網站)
- Log Server (統整ELK)
- Cache Server (Redis)
- AP Server (Schedule Job 排成)
- Queue Server (RabbitMQ)
- DB Server