Slide 1

Slide 1 text

新促購機制── 抽象化系統設計思維以促購引擎為例 Zhi-Wei Senior Software Engineer 2020/06/18 1

Slide 2

Slide 2 text

大綱 新促購機制── 簡介新促購引擎 帶來的效益 新的挑戰 總結 2

Slide 3

Slide 3 text

I am Zhi-Wei 91APP Senior Software Engineer, also Microsoft Certified Solutions Developer and Associate 3

Slide 4

Slide 4 text

新促購機制──簡介新促購引擎 4

Slide 5

Slide 5 text

背景 ● 促購(Promotion): 促購是指商店向消費者傳遞有關產品的 各種訊息,吸引消費者注意商店的產品、 激發消費者的購買欲望,並促使其實現最 終的購買行為。常用的促購方式有降價、 打折、贈送等方式。商店可根據實際情況 及市場、產品等因素選擇一種或多種促購 方式的組合。 參考資料:促銷 - MBA智庫百科、銷售促進-華人百科 圖片來源:Sales promotion - Wikimedia Commons 5

Slide 6

Slide 6 text

背景 ● 促購活動複雜且多變的折扣方式,例如: ○ 指定商品任選優惠價:滿 2 件,合計 399 圓; ○ 現折:滿 1000 圓,全部折 100 圓; ○ 第 N 件折扣:滿 2 件,第 2 件 6 折; ○ 紅配綠:紅標商品滿 1 件 + 綠標商品滿 1 件,合計 999 圓。 6

Slide 7

Slide 7 text

動機 ● 實現新促購機制的動機: ○ 使用更多變更多重的折扣方式,以搭配商店的促購活動。 ○ 簡化購物車計算金額流程,抽象化折扣計算邏輯以便日後維運。 7

Slide 8

Slide 8 text

目標 ● 統一運算規則: ○ 解決商業邏輯不一致,難以驗證溝通等問題。 ● 打造可擴充的計算引擎: ○ 折扣規則標準化,加速開發與上線時程。 8

Slide 9

Slide 9 text

挑戰 ● 統整折扣規則的挑戰: ○ 完全不同的折扣規則; ○ 完全不同的適用商品範圍; ○ 各種折扣規則的組合順序。 9

Slide 10

Slide 10 text

解決方案 ● 什麼是抽象化: ○ 提取重點:讓主系統只依照被提取的重點設計流程; ○ 隱藏細節:讓跟重點無關的細節不會影響主系統的設計。 10 參考資料:架構面試題 #4 - 抽象化思考;折扣規則的設計機制 — 安德魯的部落格

Slide 11

Slide 11 text

解決方案 ● 由購物車結帳流程抽象化促購引擎: ○ 提取重點:提取最終折扣金額; ○ 隱藏細節:隱藏折扣計算規則。 11

Slide 12

Slide 12 text

解決方案 ● 將結帳流程抽象化 促 購 引 擎 規則 #1 規則 #2 規則 #3 最終折扣金額 12 折扣計算規則

Slide 13

Slide 13 text

解決方案 ● 隱藏折扣計算細節後,購物車結帳要處理的項目: 1. 描述商品資訊(包含品名、標籤及售價); 2. 呼叫引擎進行的折扣計算; 3. 結帳的收據明細顯示。 13

Slide 14

Slide 14 text

解決方案 ● 定義系統架構 private static void Main(string[] args) { // 初始化購物車 Context 與 POS 物件。 var cart = new CartContext(); var pos = new Pos(); // 1. 購物車加入購買商品。 cart.PurchasedItems.AddRange(LoadProducts()); // POS 加入啟用的折扣規則。 pos.ActivatedRules.AddRange(LoadRules()); // 2. 對購物車 Context 進行結帳。 pos.CheckoutProcess(cart); // 3. 列印收據。 PrintReceipt(cart); } 14 範例程式碼: Andrew.DiscountDemo/Program.cs at master · Zhi-Wei/Andrew.DiscountDemo · GitHub

Slide 15

Slide 15 text

解決方案 ● POS 的結帳方法 public bool CheckoutProcess(CartContext cart) { cart.AppliedDiscounts.Clear(); // Reset Cart. cart.TotalPrice = cart.PurchasedItems.Select(p => p.Price).Sum(); // 計算總價。 // 計算折扣。 foreach (var discounts in this.ActivatedRules .Select(rule => rule.Process(cart).ToArray())) { cart.AppliedDiscounts.AddRange(discounts); cart.TotalPrice -= discounts.Select(d => d.Amount).Sum(); } return true; } 15 範例程式碼: Andrew.DiscountDemo/Pos.cs at master · Zhi-Wei/Andrew.DiscountDemo · GitHub

Slide 16

Slide 16 text

解決方案 ● 定義折扣規則的抽象化介面 public abstract class RuleBase { public int Id { get; set; } public string Name { get; set; } public string Note { get; set; } public abstract IEnumerable Process(CartContext cart); } 16 範例程式碼: Andrew.DiscountDemo/RuleBase.cs at master · Zhi-Wei/Andrew.DiscountDemo · GitHub

Slide 17

Slide 17 text

解決方案 ● 實作第一個折扣規則:任兩箱結帳 88 折 public class BuyMoreBoxesDiscountRule : RuleBase { public override IEnumerable Process(CartContext cart) { var matchedProducts = new List(); foreach (var p in cart.PurchasedItems) { matchedProducts.Add(p); if (matchedProducts.Count != this._boxCount) continue; yield return new Discount // 符合折扣 { Amount = matchedProducts.Select( product => product.Price).Sum() * this._percentOff / 100, Products = matchedProducts.ToArray(), Rule = this, }; matchedProducts.Clear(); } } } 17 範例程式碼: Andrew.DiscountDemo/BuyMoreBoxesDiscountRule.cs at master · Zhi-Wei/Andrew.DiscountDemo · GitHub

Slide 18

Slide 18 text

解決方案 ● 擴充第二個折扣規則:消費滿 1000 折抵 100 public class TotalPriceDiscountRule : RuleBase { public override IEnumerable Process(CartContext cart) { if (cart.TotalPrice > this._minDiscountPrice) { yield return new Discount { Amount = this._discountAmount, Rule = this, Products = cart.PurchasedItems.ToArray() }; } } } 18 範例程式碼: Andrew.DiscountDemo/TotalPriceDiscountRule.cs at master · Zhi-Wei/Andrew.DiscountDemo · GitHub

Slide 19

Slide 19 text

解決方案 ● 折扣規則的抽象化: ○ 將折扣規則抽象化為 RuleBase 的抽象類別; ○ 實作折扣規則本身的折扣邏輯。 19

Slide 20

Slide 20 text

解決方案 ● 多型的應用: ○ CheckoutProcess 結帳方法僅需依步驟執行; ○ 僅需透過 RuleBase 定義的 Process 方法存取。 20

Slide 21

Slide 21 text

解決方案 ● 達到目標: ○ 統 一 運 算 規 則 : 抽象化結帳流程讓折扣的運算皆交由促購引擎計算取的最終的折購金額。 ○ 打 造 可 擴 充 的 計 算 引 擎 : 抽象化折扣規則讓任何依照合約實作的折扣規則皆可擴充至促購引擎。 21

Slide 22

Slide 22 text

帶來的效益 22

Slide 23

Slide 23 text

帶來的效益 ● 新促購機制解決方案的效益: 1. 可擴充折扣規則; 2. 加快開發速度; 3. 元件化促購引擎。 23

Slide 24

Slide 24 text

帶來的效益 1. 可擴充折扣規則: ○ 我們有能力新增各類型或未知的折扣規則,來滿足多變的市場需求; ○ 今年第一季為止已擴充 8 種類型的折扣規則,受惠商店約 740 家。 24

Slide 25

Slide 25 text

帶來的效益 2. 加快開發速度: ○ 僅須著重於該折扣規則的開發即可,相對地能夠加快我們的開發速度; ○ 大幅提升開發速度約 2 至 4 倍。 25

Slide 26

Slide 26 text

帶來的效益 3. 元件化促購引擎: ○ 更容易被測試與驗證,同時也更容易開發試算或模擬工具; ○ 透過離線試算,先讓商店知道折扣後是否低於成本。 26

Slide 27

Slide 27 text

新的挑戰 27

Slide 28

Slide 28 text

新的挑戰 ● 新促購機制接下來的挑戰: ○ 新舊促購的並存; ○ 有順序性的折扣; ○ 折扣排除、擇優; ○ 折價券。 28

Slide 29

Slide 29 text

總結 29

Slide 30

Slide 30 text

總結 ● 設計系統架構時運用物件導向程式設計概念讓系統能更容易適應變化; ● 良好的抽象化結果讓系統對於未來的擴充性與維護性大幅上升; ● 經過仔細思考設計的系統會比事後最佳化更能發揮效益。 30

Slide 31

Slide 31 text

附錄 ● 範例程式碼: ○ GitHub - Zhi-Wei/Andrew.DiscountDemo ● 參考資料: ○ 架構面試題 #4 - 抽象化思考;折扣規則的設計機制 — 安德魯的部落格 ○ 抽象化 (計算機科學) - 維基百科,自由的百科全書 ○ 促銷 - MBA智庫百科 ○ 銷售促進-華人百科 31

Slide 32

Slide 32 text

Join Us: 91APP.com/careers 32