现实的业务,非常复杂。即使同一事物,在多个业务下意义可能完全不同。比如【商品】:
- 在商品详情页语境指【商品基本信息】
- 在下单页语境指【购买项】
- 在物流页面语境又是【被运送的货物】
DDD 核心思想就是让正确的领域模型发挥作用。DDD 指导开发将不同子业务单元划分为不同子领域,在各个子领域内部分别建模应对业务的复杂性。
1 背景
经典的MVC开发,因为初期业务也比较简单,为光速上线, 综合考虑成本和风险,经常创建一个大模型,各个模块都想着直接复用这同一模型。但随业务发展,各子领域的逻辑越来越复杂,对该大模型的修改就会变成一种灾难,有时明明是要改一个 A 子领域的逻辑,却莫名其妙影响到了 B 或者C 子领域的线上功能,这也是导致代码中出现一堆 ifelse 的一大源泉。
比如活动中心,主导商品的优惠活动管理、计算不同用户的优惠结果。【商品管理】和【活动管理】作为两个不同业务单元,在初期被设计为一个大的商品模型,由商品模块统一管理。
原设计之殇
但随业务发展,活动形式推陈出新,业务形态多样,需求也越来越个性化,导致如下问题日渐明显:
功能不够灵活
活动信息作为商品信息的一个属性在商品管理模块配置。
比如为了引导用户使用 App 需要设置 A 类型优惠,就在商品信息的编辑页面增加一个 A 类型活动配置项;如果某个商品的 A 类型优惠需要在 0:00 分生效,业务同学就必须在电脑前等到 0:00 更新商品信息来上线优惠活动。
如果想要创建针对所有商品都适用的优惠,按之前模式,所有商品都要设置一遍,这几乎不可接受。
不易扩展
活动信息存储在商品信息,活动信息通过商品管理模块的接口输出。
如果要新增一种活动类型,商品信息相关的表就要增加字段,商品的表会越来越大;如果要迭代一个优惠的逻辑,就有可能影响到商品管理模块的功能。
不利于迭代
由于活动信息仅作为商品的一个属性,没有自己的生命周期,所以很难去埋点统计某一次设置的活动的投入产出比,从而指导后续的功能优化。
重构目标
- 系统层面
把活动相关的业务逻辑独立出来,单独设计和实现 - 应用层面
活动中心会有自己的独立后台,负责管理活动;也会有独立的折扣计算接口,负责 C 端用户使用优惠时的计算。
落地过程
比如旅游业务售卖的商品和标品不同:
- 有些优惠不考虑人群,比如使用优惠券,所有类型的库存都可以享受
- 但如 N 人 N 折这类优惠,成人价可以享受,儿童价和单房价就不可以
基于此,对优惠中心的商品模型做了抽象,抽象出
- 【是否可参与件数计算】
- 【是否可以参与价格计算】
两个通用属性。既实现了基于业务逻辑建模,又不会陷入业务逻辑千差万别的表象中。
参考