【基于电商履约场景的 DDD 实战】DDD领域驱动设计的优势分析以及与MVC架构对比

178 阅读6分钟

🌈🌈🌈🌈🌈🌈🌈🌈
欢迎关注公众号(通过文章导读关注:【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 对比

先说一下履约场景的简单业务流程,之后再来编写代码

履约系统的作用:在用户支付成功之后,通知了电商平台,通过履约系统来履行约定,也就是在用户支付成功后,履约系统去做一系列的操作,保证商家把商品发货给用户

接下来说一下履约系统的整个流程:

  1. 履约系统收到用户支付成功后的订单

  2. 根据订单,生成履约单

  3. 预分仓:有多个发货仓库,先分配一个距离比较近的仓库

  4. 风控拦截:对一些有风险的操作进行拦截,比如说刷单、黄牛、黑客等操作

  5. 合并处理:将多个相同发货仓库的订单,合并到一起进行处理

  6. 人工审核:人工进行审核一下,检查一下订单有没有问题

    1. 重分仓:如果发现不合理,重新分配一个仓库
  7. 人工拣货,复核打包

  8. 发货:物流揽件、物流运输、物流派件、物流签收

接下来针对预分仓这一个方法,来对 DDD 和 MVC 两种架构进行分析,看一下有什么区别:

我们其实之前常用的架构思想就是 MVC 三层架构,是面向数据库思维的编码思想,而面向数据库思维进行编码会导致严重的脱离原有的业务语义

MVC 架构编码

首先说一下为什么说是面向数据库思维的方式去编码呢?

对于预分仓来说,它的业务逻辑是:

  1. 先拿到所有发货仓库的数据
  2. 再拿到所有履约单的数据
  3. 之后再去根据履约单,去和发货仓库一个一个对比,找出来最近的一个仓库
  4. 再将履约单和发货仓库的对应关系保存下来

那么按照我们原有的面向数据库的思维方式,对于第一步,要先去数据库中查询出来所有的发货仓库的数据,第二步再去数据库中查询出来所有的履约单的数据,第三步再去循环履约单以及发货仓库,找到距离最近的发货仓库,第四步再去将履约单和发货仓库的对应关系给存储到数据库中,伪代码如下:

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 有很大不同的一点,这些之后都会详细介绍