- 梳理库存业务场景
- 梳理限界上下文
-
梳理库存模型
-
占用库存:已售卖未出库库存数
-
可用库存:仓库实物库存 - 占用库存
-
实物库存:仓库中的实际库存数
-
在途库存:已采购未入库库存数
-
冻结库存:因秒杀等促销活动或仓间调拨等预占的库存数
梳理清楚之后,关于 DDD 架构选型也是要重点考虑的内容:
- 梳理领域模型与非领域模型之间关系 - 六边形架构
-
保证核心领域模型的稳定性
-
分层设计采用依赖倒置原则,保证核心领域模型的稳定性,领域层不依赖任何其他层,底层服务可以依赖高层服务所提供的接口。
- 防止定制化查询腐化领域模型
我们通过引入 CQRS 模式,隔离命令与查询领域模型。
-
- 防止与其他限界上下文交互导致领域模型腐化
如下图所示采购上下文通过防腐层 (ACL) 将仓储库存核心上下文中的仓库信息映射为自身上下文中的仓库值对象,防止仓库信息依赖腐化。
- 架构最终落地 -COLA
- 库存变更场景相关单据状态一致性保障
从库存变更场景中,可以看到围绕库存变更在不同的业务层存在不同的业务单据,上层业务层单据状态变更依赖底层仓储核心单据状态变更,如采购入库单入库状态变更为入库完成则采购单状态也会变更为已完成,如销售出库单状态变更为出库完成则销售发货单状态会变更为已发货。
另外,如果您正在学习Spring Cloud,推荐一个连载多年还在继续更新的免费教程:https://blog.didispace.com/spring-cloud-learning/
-
- 方案选择
最终我们采用 EventStore 方案,使用 EventStore 数据流程如下:
上图中黄色部分为领域事件异常处理。
- 发布领域事件代码如下:
-
订阅领域事件
-
注册订阅组
-
- 在订阅组中声明订阅事件
-
在持续集成开发过程中如何同时保障效率和质量 - 单元测试保驾护航
-
核心领域模型添加单元测试,对应 Domain 测试
-
核心业务接口场景添加单元测试,对应 CmdExe 测试
-
引入 Mockito 库,mock 相关接口和数据,验证流程环节是否正确
-
在单测代码中造单测相关数据,保证单测数据可靠性
-
单测采用 H2 数据库,避免测试过后留痕,影响后续单测,同时提升单测执行效率
-
减少或不依赖其他中间件,如 Dubbo、Kafka 等,如依赖可考虑直接 Mock
-
git push 后 CI 开启自动单元测试
最终,回顾这次改造工作,我认为收益可以分为五点:
-
实际库存准确,彻底解决仓库库存不准问题,同时为校准销售库存提供基准参考;
-
功能扩展方便,如后续快速对接财务系统;
-
快速定位问题(代码结构清晰,库存变更有据可查且上下文清晰);
-
沉淀出较通用的事件组件 EventStore,后续在 Keep 电商内部快速推广复用;
-
沉淀出一套比较成熟的 DDD 最佳实践,后续快速推广至 Keep 电商库存系统重构、售后重构。
可以看出,收益还是非常喜人的。大部分同学关注 DDD 是因为微服务,没错,DDD 可以说是与微服务天生互补的,DDD 领域面向划分业务模型边界,微服务面向将单体架构拆分为多个微服务,至于如何拆微服务,DDD 领域拆分则是一个非常好的微服务拆分方式。
欢迎关于 DDD,如果你想进一步交流探讨,也可以在本文下留言,期待大家的分享能够带来更多的启发。
作者介绍
武清明,从业 12 年,近 8 年一直在互联网电商行业一线从事系统研发,之前在京东和万达电商负责过仓储系统、订单系统、促销系统等研发工作。目前在 Keep 负责商业化业务中台研发和规划工作。擅长电商业务系统架构设计,采用 DDD 合理简单化设计复杂电商系统,提升系统功能模块的复用性和扩展性。
往期推荐