DDD领域驱动设计实战电商活动中心重构

现实的业务,非常复杂。即使同一事物,在多个业务下意义可能完全不同。比如【商品】:

  • 在商品详情页语境指【商品基本信息】
  • 在下单页语境指【购买项】
  • 在物流页面语境又是【被运送的货物】

DDD 核心思想就是让正确的领域模型发挥作用。DDD 指导开发将不同子业务单元划分为不同子领域,在各个子领域内部分别建模应对业务的复杂性。

1 背景

经典的MVC开发,因为初期业务也比较简单,为光速上线, 综合考虑成本和风险,经常创建一个大模型,各个模块都想着直接复用这同一模型。但随业务发展,各子领域的逻辑越来越复杂,对该大模型的修改就会变成一种灾难,有时明明是要改一个 A 子领域的逻辑,却莫名其妙影响到了 B 或者C 子领域的线上功能,这也是导致代码中出现一堆 ifelse 的一大源泉。


比如活动中心,主导商品的优惠活动管理、计算不同用户的优惠结果。【商品管理】和【活动管理】作为两个不同业务单元,在初期被设计为一个大的商品模型,由商品模块统一管理。

DDD领域驱动设计实战电商活动中心重构

原设计之殇

但随业务发展,活动形式推陈出新,业务形态多样,需求也越来越个性化,导致如下问题日渐明显:

功能不够灵活

活动信息作为商品信息的一个属性在商品管理模块配置。

比如为了引导用户使用 App 需要设置 A 类型优惠,就在商品信息的编辑页面增加一个 A 类型活动配置项;如果某个商品的 A 类型优惠需要在 0:00 分生效,业务同学就必须在电脑前等到 0:00 更新商品信息来上线优惠活动。


如果想要创建针对所有商品都适用的优惠,按之前模式,所有商品都要设置一遍,这几乎不可接受。

不易扩展

活动信息存储在商品信息,活动信息通过商品管理模块的接口输出。

如果要新增一种活动类型,商品信息相关的表就要增加字段,商品的表会越来越大;如果要迭代一个优惠的逻辑,就有可能影响到商品管理模块的功能。

不利于迭代

由于活动信息仅作为商品的一个属性,没有自己的生命周期,所以很难去埋点统计某一次设置的活动的投入产出比,从而指导后续的功能优化。

重构目标

  • 系统层面
    把活动相关的业务逻辑独立出来,单独设计和实现
  • 应用层面
    活动中心会有自己的独立后台,负责管理活动;也会有独立的折扣计算接口,负责 C 端用户使用优惠时的计算。

落地过程

比如旅游业务售卖的商品和标品不同:

  • 有些优惠不考虑人群,比如使用优惠券,所有类型的库存都可以享受
  • 但如 N 人 N 折这类优惠,成人价可以享受,儿童价和单房价就不可以

基于此,对优惠中心的商品模型做了抽象,抽象出

  • 【是否可参与件数计算】
  • 【是否可以参与价格计算】


两个通用属性。既实现了基于业务逻辑建模,又不会陷入业务逻辑千差万别的表象中。


参考

上一篇:duilib 修复CTreeViewUI控件动态添加子控件时,对是否显示判断不足的bug


下一篇:2020年6月9日 邀您参加2020年阿里云线上峰会——存储专场