如何一步一步用DDD設計一個電商網站(六)—— 給購物車加點料,整合售價上下文

來源:互聯網
上載者:User

標籤:cts   業務   rtt   資料類型   處理   物理   emd   合作   font   

閱讀目錄
  • 前言
  • 如何在一個項目中實現多個內容相關的業務
  • 售價上下文與購買內容相關的整合
  • 結語

 

一、前言

  前幾篇已經實現了一個最簡單的購買過程,這次開始往這個過程中增加一些東西。比如促銷、會員價等,在我們的第一篇文章(如何一步一步用DDD設計一個電商網站(一)—— 先理解核心概念)中規劃的上下文映射圖可以看到,這些都屬於一個獨立的上下文(售價上下文)。

 

二、如何在一個項目中實現多個內容相關的業務

  一般情況下,為了更好的分而治之,把不同的上下文作為單獨的service,然後通過rpc架構(如WCF)來對其訪問是個比較常見的做法。但是在一些小型團隊中,雖然劃分出了不同上下文,但是我們的Team Dev還是同一個。在這種情況下,我個人一般的做法是直接在同一個解決方案中建立不同的項目去做,但是這裡需要在解決方案中明確的劃分好不同上下文之間的邊界,通過代碼審核等手段管理好這個邊界不被破壞。

  

                      【圖1】

  增加的幾個項目1所示。

  

三、售價上下文與購買內容相關的整合

  根據我們第一篇如何一步一步用DDD設計一個電商網站(一)—— 先理解核心概念所定義的上下文映射圖和9種整合模式可以看出,這2個上下文在同一個子域中,並且在我們實際業務情境中,這2者又是相輔相成,所以售價上下文和購買上下文是一種合作關係。確立這個關係之後,那麼這個促銷的計算邏輯到底是放到哪個上下文種做更合適呢?我們先整理一下幾種可能的方式:

  1.購買上下文把購物車中的商品資訊丟給售價上下文 --> 售價上下文進行計算 --> 把結果再返回給購買上下文。

  2.購買上下文從銷價上下文擷取相關會員價和促銷資訊 --> 再本地的購物車對象基礎上進行運算,並直接可運用結果。

  3.再抽出一個專門的計算服務(隸屬於售價上下文),去做這個計算的動作。購買上下文把購物車中的商品資訊丟給計算服務 --> 計算上下文從銷價上下文擷取到相關會員價和促銷資訊 --> 計算 --> 返回結果給購買上下文

  我相信1和2是比較主流的2個方式。但是方式2是把售價上下文僅作為一種資料的提供方,這就把合作關係變成了一個上下遊的關係,並且這種方式使得促銷規則和購物車強耦合到了一起,不利於促銷規則的變化。在這裡售價上下文只起了一個簡單的資料維護作用,無法完全控制“售價”的定義,沒有很好的做到職責分離。方式1和3對購買上下文來說其實是沒有區別的,只是方式3讓整個資料互動的鏈路多了一層,會產生額外的開銷,好處是服務的粒度更細了,需要結合實際情況權衡一下得失。這裡我選擇1方式來實現,因為我們在項目初期,還是儘可能的減少非業務目的的拆分導致的額外成本。

  好了,確定了整合方式之後,先把2個上下文之間用於資料互動的DTO模型定一下,如2(售價內容相關的DTO模型),圖3(購買上下文中與前者對應的值對象)。

 

                     【圖2】

                  【圖3】

  另外在圖3中可以發現增加了一個ISellingPriceService,抽象了與售價內容相關的互動。那麼我們在Mall.Infrastructure.Translators項目中增加對這個內容相關的防腐層處理,老3樣SellingPriceAdapter(發起上下文資料請求的適配器)、SellingPriceService(實現ISellingPriceService)、SellingPriceTranslator(把遠端資料物件轉換成本地的值對象),代碼很簡單大家可以在源碼中查看。需要注意的是,這裡的Mall.Infrastructure.Translators項目僅增加了對Mall.Application.SellingPrice項目的引用,類似於把它當作一個遠端資源來對待(按上面所說,如果實際由不同的團隊負責可以物理上的分離到2個解決方案中)。

  最後建立一個CartService,裡面的GetCart()方法——擷取購物車資訊,來作為調用發起方。這其中的實現使用了最簡單的方式,本地不做任何的資料冗餘,代碼如下:

    public class CartService    {        private readonly static ConfirmUserCartExistedDomainService _confirmUserCartExistedDomainService = new ConfirmUserCartExistedDomainService();        public CartDTO GetCart(string userId)        {            var cart = _confirmUserCartExistedDomainService.GetUserCart(userId);            if (cart.IsEmpty())            {                return null;            }            var sellingPriceCart = DomainRegistry.SellingPriceService().Calculate(cart);            return ConvertToCart(cart, sellingPriceCart);        }        private CartDTO ConvertToCart(Cart cart, SellingPriceCart sellingPriceCart)        {            return new CartDTO            {                CartItemGroups = sellingPriceCart.CalculatedFullGroups.Select(ent => new CartItemGroupDTO                {                    CartItems = ent.CalculatedCartItems.Select(e => ConvertToCartItem(e, cart.GetCartItem(e.ProductId))).ToArray(),                    ReducePrice = ent.ReducePrice                }).ToArray(),                CartItems = sellingPriceCart.CalculatedCartItems.Select(ent => ConvertToCartItem(ent, cart.GetCartItem(ent.ProductId))).ToArray()            };        }        private CartItemDTO ConvertToCartItem(SellingPriceCartItem sellingPriceCartItem, CartItem cartItem)        {            var product = DomainRegistry.ProductService().GetProduct(cartItem.ProductId);            return new CartItemDTO            {                ProductId = cartItem.ProductId,                ProductName = product == null ? "商品已失效" : product.SaleName,                ReducePrice = sellingPriceCartItem.ReducePrice,                SalePrice = cartItem.Price            };        }    }    

 

 四、結語

  這次有個全域改動這裡提一下,我在本次編碼中把之前所有的Guid標識全部改為了string類型,弱化了對唯一標識的資料類型約束,提高可擴充性(如自增欄位、其它自訂的唯一標識等),另外還把購物項中的Price改為了UnitPrice,讓語義更加清晰。本篇內容比較粗,歡迎大家探討。

 

 

本文的源碼地址:https://github.com/ZacharyFan/DDDDemo/tree/Demo6。

 

 

Zachary_Fan
出處:http://www.cnblogs.com/Zachary-Fan/p/6087752.html

如何一步一步用DDD設計一個電商網站(六)—— 給購物車加點料,整合售價上下文

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.