前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于聚合根、领域事件的那点事——深入浅出理解DDD

关于聚合根、领域事件的那点事——深入浅出理解DDD

作者头像
京东技术
发布2023-08-22 15:44:36
1.1K0
发布2023-08-22 15:44:36
举报
文章被收录于专栏:京东技术

Tech 导读 领域驱动设计(Domain-Driven Design,简称DDD)是一种软件开发方法论,旨在帮助开发人员更好地理解和解决复杂领域的问题。在DDD中,聚合根和领域事件是两个核心概念,它们在设计和实现领域模型时起到了重要的作用。本文将通过简单的举例方式,深入浅出地介绍聚合根和领域事件,帮助读者更好地理解DDD的核心思想和实践方法。希望本文能够为读者提供有价值的知识和启发,帮助大家在软件开发中更好地应用DDD的思想和方法。

01

前言

在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!

最近有空会跟同事讨论DDD架构的实践落地的情况,但真实情况是,实际中对于领域驱动设计中的实体、值对象、聚合根、领域事件这些战术类的实践落地,每个人理解依然因人而异,大概率是因为这些概念还是有一些抽象,同时有有别于传统的MVC架构开发。

在此,通过小demo的方式跟大家分享一下对DDD中战术层级的理解,算是抛砖引玉,该理解仅代表个人在现阶段的一个理解,也可能未来随着业务经验深入,还会有不同的理解。

既然说是小demo,还是要从业务场景出发,也就是最熟知的电商业务场景说起。但是该篇文章里,会简化一些实际业务场景中的复杂度,通过最小颗粒度的demo,来反映实践过程中的基本问题。

02

一个简单的demo业务场景

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

话不多说,先抛出假设的一个业务场景,就是熟知的电商网站下单购物的场景。具体细节如下:

2.1 实体

  • 商品:拥有唯一标识、名称、价格、库存等属性。
  • 订单:拥有唯一标识、下单时间、状态等属性。订单包含多个订单项。

2.2 值对象

  • 地址:拥有省、市、区、详细地址等属性。

2.3 领域事件

  • 订单创建事件:当用户下单时触发该事件,包含订单信息、商品信息等数据。
  • 订单支付事件:当用户完成支付时触发该事件,包含订单信息、支付金额等数据。
  • 订单发货事件:当商家发货时触发该事件,包含订单信息、快递公司、快递单号等数据。

2.4 聚合根

  • 商品聚合根:包含商品实体和相关的值对象,负责商品的创建、修改、查询等操作。
  • 订单聚合根:包含订单实体和相关的值对象,负责订单的创建、修改、查询等操作。

2.5 对外接口服务

  • 创建订单接口:用户提交购买请求后,系统创建相应的订单,并触发订单创建事件。
  • 支付订单接口:用户完成支付后,系统更新订单状态,并触发订单支付事件。
  • 发货接口:商家发货后,系统更新订单状态,并触发订单发货事件。
  • 查询订单接口:用户可以根据订单号等条件查询自己的订单信息。

该demo中,商品和订单是两个核心领域概念,分别由对应的聚合根负责管理。同时,通过定义领域事件,实现了不同业务场景下的数据更新和通知。最后,对外提供了一组简单的接口服务,方便系统的使用和扩展。

03

demo的java代码实现

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

好了,有了以上对业务场景的充分剖析,确定了子域,接下来该写代码。

3.1 商品实体类

代码语言:javascript
复制
// 省略getter/setter方法
public class Product {
    private Long id;
    private String name;
    private BigDecimal price;
    private Integer stock;
}

3.2 订单实体类

代码语言:javascript
复制
// 省略getter/setter方法
public class Order {
    private Long id;
    private LocalDateTime createTime;
    private Integer status;
    private List orderItems;
}

3.3 订单项实体类

代码语言:javascript
复制
// 省略getter/setter方法
public class OrderItem {
    private Long id;
    private Product product;
    private Integer quantity;
    private BigDecimal price;
}

3.4 地址值对象

代码语言:javascript
复制
// 省略getter/setter方法 
public class Address {
    private String province;
    private String city;
    private String district;
    private String detail;
}

3.5 领域事件类

代码语言:javascript
复制
//订单创建领域事件
public class OrderCreatedEvent {
    private Order order;
    private List orderItems;

    public OrderCreatedEvent(Order order, List orderItems) {
        this.order = order;
        this.orderItems = orderItems;
    }
}


//订单支付领域事件
public class OrderPaidEvent {
    private Order order;
    private BigDecimal amount;

    public OrderPaidEvent(Order order, BigDecimal amount) {
        this.order = order;
        this.amount = amount;
    }
}

//订单
public class OrderShippedEvent {
    private Order order;
    private String expressCompany;
    private String expressNo;

    public OrderShippedEvent(Order order, String expressCompany, String expressNo) {
        this.order = order;
        this.expressCompany = expressCompany;
        this.expressNo = expressNo;
    }
}

3.6 商品聚合根

代码语言:javascript
复制
public class ProductAggregate {
    private ProductService productService;

    public void createProduct(Product product) {
        productService.create(product);
    }

    public void updateProduct(Product product) {
        productService.update(product);
    }

    public void deleteProduct(Long productId) {
        productService.delete(productId);
    }

    public Product getProductById(Long productId) {
        return productService.getById(productId);
    }
}

3.7 订单聚合根

代码语言:javascript
复制
public class OrderAggregate {
    private OrderService orderService;

    public void createOrder(Order order, List orderItems) {
        orderService.create(order);
        // 触发订单创建事件 
        DomainEventPublisher.publish(new OrderCreatedEvent(order, orderItems));
    }

    public void payOrder(Long orderId, BigDecimal amount) {
        orderService.pay(orderId, amount);
        // 触发订单支付事件
        DomainEventPublisher.publish(new OrderPaidEvent(orderService.getById(orderId), amount));
    }

    public void shipOrder(Long orderId, String expressCompany, String expressNo) {
        orderService.ship(orderId, expressCompany, expressNo);
        // 触发订单发货事件 
        DomainEventPublisher.publish(new OrderShippedEvent(orderService.getById(orderId), expressCompany, expressNo));
    }

    public Order getOrderById(Long orderId) {
        return orderService.getById(orderId);
    }
}

04

总结

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目

通过以上demo,对于实体和值对象,大家会很好理解,并且很直观。但是,额外想重点解释一下聚合根和领域事件的概念。

4.1 聚合根

从上面的demo可以看出,在合根类中,定义了商品和订单的增、删、查等操作,并且为订单定义了创建订单、支付订单、发货等业务逻辑代码。

聚合根是一个对象,它代表一组相关联的对象的整体。在聚合根内部,可以包含多个实体对象和值对象。聚合根通常可以通过唯一标识符来进行识别和访问。它是整个聚合的管理者,负责维护聚合之内的一致性,并协调各个实体对象之间的关系。聚合根通常具有丰富的行为和操作,可以对聚合内部的对象进行复杂的操作。

所以说,真正的聚合根内的方法是基于充血模型封装的,而不是仅仅是对对象的数据封装。在聚合根中,对象不仅封装了数据,还包含了相应的行为和业务逻辑。这意味着在一个聚合根中,对象可以自己处理自己的业务逻辑,而不需要外部的控制。就如同demo中所写的那样,订单对象可能包含一些关于订单处理和交付的方法,如确认订单、取消订单、发货等。

4.2 领域事件

领域事件是DDD中最重要的概念之一,它是解决子域之间耦合的重要手段,因为它们提供了一种将领域概念和业务语言转化为代码的方法。当一个领域事件发生时,它会触发一些操作,这些操作可能会更改系统的状态,也可能会导致其他领域事件的发生。通过对领域事件进行建模,可以更好地了解业务过程并设计出更加符合实际需求的系统。

在DDD中,领域事件通常由三个部分组成:

  1. 事件名称:这个名称应该能够简洁明了地描述事件所代表的业务意义。
  2. 相关数据:这些数据包含了事件发生时与事件相关的所有信息。例如,在一个电子商务系统中,如果订单被提交,则订单信息以及买家和卖家的信息都应该包括在该事件中。
  3. 发送者和接收者:发送者通常是触发事件的对象,接收者则是事件处理的对象。

领域事件在DDD中有很多用途。例如,它们可以用来触发其他业务流程、更新数据库或通知其他子系统。它们还可以用于解决一些复杂的业务逻辑问题,例如并发、数据同步和错误处理等等。

总之,领域事件是DDD架构中非常重要的概念,它可以帮助更好地理解业务过程,设计出更加符合实际需求的系统,并提高系统的可维护性和可扩展性。

打造SAAS化服务的会员徽章体系,可以作为标准的产品化方案统一对外输出。结合现有平台的通用能力,实现会员行为全路径覆盖,并能结合企业自身业务特点,规划相应的会员精准营销活动,提升会员忠诚度和业务的持续增长。

底层能力:维护用户基础数据、行为数据建模、用户画像分析、精准营销策略的制定

▪功能支撑:会员成长体系、等级计算策略、权益体系、营销底层能力支持

▪用户活跃:会员关怀、用户触达、活跃活动、业务线交叉获客、拉新促活

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京东技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一个简单的demo业务场景
  • demo的java代码实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档