本系列全部文章html
如何一步一步用DDD設計一個電商網站(一)—— 先理解核心概念git
如何一步一步用DDD設計一個電商網站(二)—— 項目架構程序員
如何一步一步用DDD設計一個電商網站(三)—— 初涉核心域github
如何一步一步用DDD設計一個電商網站(四)—— 把商品賣給用戶微信
如何一步一步用DDD設計一個電商網站(五)—— 停下腳步,從新出發網絡
如何一步一步用DDD設計一個電商網站(六)—— 給購物車加點料,集成售價上下文架構
如何一步一步用DDD設計一個電商網站(七)—— 實現售價上下文框架
如何一步一步用DDD設計一個電商網站(八)—— 會員價的集成分佈式
如何一步一步用DDD設計一個電商網站(九)—— 當心陷入值對象持久化的坑函數
如何一步一步用DDD設計一個電商網站(十)—— 一個完整的購物車
如何一步一步用DDD設計一個電商網站(十一)—— 最後的準備
如何一步一步用DDD設計一個電商網站(十二)—— 提交併生成訂單
如何一步一步用DDD設計一個電商網站(十三)—— 領域事件擴展
閱讀目錄
結合咱們本次系列的第一篇博文中提到的上下文映射圖(傳送門:如何一步一步用DDD設計一個電商網站(一)—— 先理解核心概念),得知咱們這個電商網站的核心域就是銷售子域。由於電子商務是以信息網絡技術爲手段,以商品交換爲中心的商務活動,一個好的核心域設計能夠大大提高企業的競爭力和對市場變化的相應速度。
那麼咱們開始設計領域對象。對於設計領域對象的基本概念不瞭解的能夠先閱讀個人該系列第二篇文章(傳送門:如何一步一步用DDD設計一個電商網站(二)—— 項目架構)。
我相信咱們大部分人會以以下的方式去存放咱們定義的基類,見圖1。
【圖1】
這是一種比較常規的技術分層思惟方式產生的結果,在某些項目文件中或多或少有那麼幾個"Base"、"Core"、"Common"等的文件夾存放着一些通用的類,它們起着對當前項目中類的抽象、實現通用性支撐性功能的做用。然而在DDD中這些都應屬於基礎設施層的事情,這樣可以保證其餘層專一於自身的職責,不會把本應內聚的東西泄露到這些類中。如咱們當前的領域層就專一於領域建模,裏面的概念所有與通用語言相關。說幹就幹,搬到基礎設施層去,再取個能表達出一致概念的名字的模塊存放,如圖2。
【圖2】
「銷售」用通俗的話講就是「把商品賣給用戶」,這幾個字中就已經凸顯出幾個概念:「商品」,「用戶」,「賣」。如下就是」商品「和」用戶「的代碼實現:
【圖3】
【圖4】
我相信有許多人會以圖3和圖4的方式定義咱們的商品和用戶,乍一看的確符合對商品、用戶概念的獨立的理解。但在DDD中有不一樣的限界上下文,每一個限界上下文專一處理自身的業務,多個限界上下文之間是以協做的方式工做。保證多個限界上下文之間的良好協做關係的方式是提升自治性。提升自治性的方式又有不少,技術方面如領域事件、消息隊列、事件源等,這裏暫時不展開描述。從代碼層面來看,建模的時候只獲取對當前上下文業務處理剛恰好大小的數據,也能夠提升當前項目的自治性。
根據咱們劃分的上下文映射圖,用戶和商品是屬於另外的上下文的,那麼在這裏咱們都應該建模爲值對象,由於咱們是沒法直接修改這些對象的內部屬性的。另外,在上面2個圖中,獲取其餘上下文中的資源時,咱們做爲客戶方基本上是不會原封不動的消費服務方提供的數據的。好比這裏面的Product.PermitNo(批文號),在大部分行業裏,它與銷售商品沒什麼關係。再如User.BlockedBalance(凍結餘額),在銷售的過程當中,只須要知道用戶有多少可用餘額就行了。這個思路總結一下就是,從業務角度咱們不求大而全,只求恰好知足當前業務便可,可是當業務發生變化的時候咱們的領域模型也要及時反映出調整後的通用語言概念。獲得修改後的模型:
【圖5】
【圖6】
對了,不論是值對象仍是實體和聚合,習慣在構造函數中的作好守衛驗證,有利於表達出什麼樣的領域對象是合法的。
在某些背景下一個限界上下文是做爲獨立的服務對外提供API進行訪問的,特別在電商行業,分佈式系統的構建是個廣泛狀況,方式也多元化,各類RPC框架、Restful等技術選型,SOA、微服務等實現理念層出不窮。如何最大化的下降技術變動和業務變化致使的上下文劃分調整的影響,也是咱們要考慮的重要問題。
對於咱們.Net開發人員來講,在分佈式場景下用的最多的方式無非是WebAPI和WCF了。這種方式也就是在第一篇文章中所提到的發佈語言和開放主機服務,那麼對於客戶端來講須要作好防腐層(第一篇文章中有提到)的工做,好避免外部上下文的概念侵入到自身的領域概念中。一個廣泛的防腐層實現時序圖,其中真正負責防腐層工做的是XXXAdapter和XXXTranslator,以下(摘自[Vaughn Vernon]《實現領域驅動設計》):
【圖7】
咱們這裏實現的相關類以下圖所示定義:
【圖8】
其中1存放着訪問遠程資源的接口定義,2是其實現方式。這樣設計的好處是,對於領域層的建模隱藏了數據獲取的實現細節。而且當咱們實際開發的時候可能因爲須要配合服務方還未準備好,可是這絲絕不影響咱們的開發工做,咱們能夠定義個Mock類來實現這裏的IRemoteServices中的接口,就能夠順利地進行開發工做。
其中ProductAdapter、UserAdapter分別負責請求商品上下文和用戶上下文並取得原始結果,ProductTranslator、UserTranslator則是經過解析原始結果,轉換爲我方上下文中須要的領域模型概念。如下則是核心部分的實現:
【圖9】
【圖10】
做者:Zachary
出處:https://zacharyfan.com/archives/121.html
▶關於做者:張帆(Zachary,我的微信號:Zachary-ZF)。堅持用心打磨每一篇高質量原創。歡迎掃描右側的二維碼~。
按期發表原創內容:架構設計丨分佈式系統丨產品丨運營丨一些思考。
若是你是初級程序員,想提高但不知道如何下手。又或者作程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關注個人公衆號「跨界架構師」,回覆「技術」,送你一份我長期收集和整理的思惟導圖。
若是你是運營,面對不斷變化的市場一籌莫展。又或者想了解主流的運營策略,以豐富本身的「倉庫」。歡迎關注個人公衆號「跨界架構師」,回覆「運營」,送你一份我長期收集和整理的思惟導圖。