🌈🌈🌈🌈🌈🌈🌈🌈
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
🍁🍁🍁🍁🍁🍁🍁🍁
基于电商履约场景的 DDD 实战
介绍
DDD(领域驱动设计,Domain-Driven Design),是一种架构设计的思想,那么使用 DDD 和 MVC 两种架构思想设计出来的系统的区别就在于:
- MVC 是面向数据库思维设计的,代码混乱,后期不易维护
- DDD 是面向业务逻辑设计的,更易于维护,代码清晰易懂
现在 DDD 架构比较火,对于大型项目来说,通过 DDD 对不同业务进行界限划分,使得系统结构清晰,方法主流程清晰,而对于小型项目来说,如果过度使用 DDD 可能会导致不必要的复杂性
学习 DDD 一定要和 MVC 进行对比,因为我们平常用的最多的就是 MVC,那么面试的时候,面试官一定会问你,为什么要学习 DDD?DDD 和 MVC 有什么区别呢?这些东西,在学完 DDD 之后,一定要自己总结一下,要不然只能是稀里糊涂的了解 DDD!
接下来会根据履约场景分别按照 DDD 和 MVC 思想写出对应的代码,来对比一下思想上的差异
DDD 和 MVC 对比
先说一下履约场景的简单业务流程,之后再来编写代码
履约系统的作用:在用户支付成功之后,通知了电商平台,通过履约系统来履行约定,也就是在用户支付成功后,履约系统去做一系列的操作,保证商家把商品发货给用户
接下来说一下履约系统的整个流程:
- 履约系统收到用户支付成功后的订单
- 根据订单,生成履约单
- 预分仓:有多个发货仓库,先分配一个距离比较近的仓库
- 风控拦截:对一些有风险的操作进行拦截,比如说刷单、黄牛、黑客等操作
- 合并处理:将多个相同发货仓库的订单,合并到一起进行处理
- 人工审核:人工进行审核一下,检查一下订单有没有问题
- 重分仓:如果发现不合理,重新分配一个仓库
- 人工拣货,复核打包
- 发货:物流揽件、物流运输、物流派件、物流签收
接下来针对预分仓这一个方法,来对 DDD 和 MVC 两种架构进行分析,看一下有什么区别:
我们其实之前常用的架构思想就是 MVC 三层架构,是面向数据库思维的编码思想,而面向数据库思维进行编码会导致严重的脱离原有的业务语义
MVC 架构编码
首先说一下为什么说是面向数据库思维的方式去编码呢?
对于预分仓来说,它的业务逻辑是:
- 先拿到所有发货仓库的数据
- 再拿到所有履约单的数据
- 之后再去根据履约单,去和发货仓库一个一个对比,找出来最近的一个仓库
- 再将履约单和发货仓库的对应关系保存下来
那么按照我们原有的面向数据库的思维方式,对于第一步,要先去数据库中查询出来所有的发货仓库的数据,第二步再去数据库中查询出来所有的履约单的数据,第三步再去循环履约单以及发货仓库,找到距离最近的发货仓库,第四步再去将履约单和发货仓库的对应关系给存储到数据库中,伪代码如下:
public class FulfillService {
// 预分仓逻辑
public void preAllocateWarehouse() {
// 1.查询仓库
warehouseDao.find();
// 2.查询履约单
orderFulfillDao.find();
// 3.将订单与仓库进行一系列匹配操作
for (orderFulfill orderFulfill : orderFulfills) {
for (Warehouse warehouse : warehouses) {
// ...匹配
}
}
// 4.将履约单与仓库对应关系存储到数据库中
orderAllocateWarehouseDao.save();
}
}
这样写出来预分仓的代码,里边会先有一堆的数据库查询,之后再去 for 循环遍历,之后再去将数据保存在数据库中,这与原有的业务语义发生了脱离,本来预分仓方法的目的是要拿履约单和仓库进行匹配,找到最适合的发货仓库,结果通过面向数据库思维,先添加了很多数据库操作的边干逻辑,从而导致整个代码的主干流程不清晰
如果你作为一个产品经理,来看这一段代码,你可能根本不知道这一堆数据库查询以及 for 循环到底是干嘛的
这就是 MVC 架构所带来的缺点,当代码多了之后,整个结构混乱,不宜维护
DDD 架构编码
上边就是通过 MVC 架构设计的代码,整个过程中都是以面向数据库思维编写的,这样的系统如果发展了几年之后,可能根本就没有人愿意来接手这个代码
接下来看一下按照 DDD 架构写出来的代码,这里写的比较简单,主要是和 MVC 对比,后边会将履约场景的代码给规范的写出来
public class FulfillService {
// 预分仓逻辑
public void preAllocateWarehouse() {
// 1.取出履约单
OrderFulfill orderFulfill = orderFulfillRepository.getById(orderId);
// 2.取出仓库信息
Warehouses warehouses = warehouseRepository.find();
// 3.寻找距离履约单最近的仓库
Warehouse warehoiuse = warehouses.searchNearest(orderFulfill);
// 4.检查仓库的库存是否充足
Boolean checkInventoryResult = warehouse.checkInventoryResult(orderFulfill);
if (!checkInventoryResult) {
return;
}
// 5.锁定库存
warehouse.lockInventory(orderFulfill);
// 6.将仓库分给履约单
orderFulfill.allocate(warehouse);
}
}
上边是根据 DDD 思想写出来的代码,可以看到,就算你不是开发人员,你来看,整个方法的主干流程非常清晰,不会有很多数据库操作来干扰视线
这里 DDD 架构中,上边比如说寻找离履约单最近的仓库,我们是把方法写到 Warehouses
中去了,分配给履约单的方法写到 OrderFulfill
中去了,这两个其实相当于是实体类,之前在 MVC 中,肯定是不会向实体类中写方法的,这也是 DDD 与 MVC 有很大不同的一点,这些之后都会详细介绍