关于聚合根,领域事件的那点事---深入浅出理解DDD_当前聚焦

2023-04-27 16:28:41 来源:博客园

作者:京东物流 赵勇萍

前言

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


【资料图】

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

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

一个简单的demo业务场景

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

1. 实体:

• 商品:拥有唯一标识、名称、价格、库存等属性。

• 订单:拥有唯一标识、下单时间、状态等属性。订单包含多个订单项。

2. 值对象:

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

3. 领域事件:

• 订单创建事件:当用户下单时触发该事件,包含订单信息、商品信息等数据。

• 订单支付事件:当用户完成支付时触发该事件,包含订单信息、支付金额等数据。

• 订单发货事件:当商家发货时触发该事件,包含订单信息、快递公司、快递单号等数据。

4. 聚合根:

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

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

5. 对外接口服务:

• 创建订单接口:用户提交购买请求后,系统创建相应的订单,并触发订单创建事件。

• 支付订单接口:用户完成支付后,系统更新订单状态,并触发订单支付事件。

• 发货接口:商家发货后,系统更新订单状态,并触发订单发货事件。

• 查询订单接口:用户可以根据订单号等条件查询自己的订单信息。

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

demo的java代码实现

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

商品实体类:
// 省略getter/setter方法public class Product {    private Long id;    private String name;    private BigDecimal price;    private Integer stock;}

2. 订单实体类

// 省略getter/setter方法public class Order {    private Long id;    private LocalDateTime createTime;    private Integer status;    private List orderItems;}

3. 订单项实体类

// 省略getter/setter方法public class OrderItem {    private Long id;    private Product product;    private Integer quantity;    private BigDecimal price;}

4. 地址值对象

// 省略getter/setter方法 public class Address {    private String province;    private String city;    private String district;    private String detail;}

5. 领域事件类

//订单创建领域事件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;    }}

6. 商品聚合根

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);    }}

7. 订单聚合根

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);    }}
总结

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

1. 聚合根

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

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

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

2. 领域事件

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

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

事件名称:这个名称应该能够简洁明了地描述事件所代表的业务意义。

相关数据:这些数据包含了事件发生时与事件相关的所有信息。例如,在一个电子商务系统中,如果订单被提交,则订单信息以及买家和卖家的信息都应该包括在该事件中。

发送者和接收者:发送者通常是触发事件的对象,接收者则是事件处理的对象。

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

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

标签:

关于聚合根,领域事件的那点事---深入浅出理解DDD_当前聚焦

2023-04-27

每日时讯!今日果酱股票价格一览,受益的果酱概念股票有哪些?

2023-04-27

【全球新视野】宝山这个案例获评上海市2022年度行政执法“十大案例” !

2023-04-27

2023年中国工业企业IT支出将超3000亿元

2023-04-27

2+1链动系统开发,4.0讲解

2023-04-27

动态焦点:一佳YIJIA品牌介绍_一佳接触器

2023-04-27

天天讯息:想在五一自在游云南,这份攻略请收好

2023-04-27

一季度河南省房地产开发投资1322.87亿元 同比下降5.1%

2023-04-27

为什么会有啤酒肚?

2023-04-27

增值税勾选认证平台登录不上去_增值税勾选认证平台 全球速看

2023-04-27

Broadwell之后是Braswell14nm工艺支援DDR4记忆体

2023-04-27

中国科学院院士、东南大学教授段进:城市发展植入空间基因 不再千城一面 全球微速讯

2023-04-27

烽火通信:4月26日融资买入9530.03万元,融资融券余额7亿元

2023-04-27

当前热门:“张继科事件”后景甜携新剧重回巅峰 状态转好

2023-04-27

全国将迎道路出行高峰 公安部预警“五一”交通安全

2023-04-27

河南一季度GDP同比增长5%

2023-04-27

中国燃气(00384.HK):4月26日南向资金减持129.6万股

2023-04-27

环球热文:四川民营经济总量超3万亿元

2023-04-27

热门:女和男脱下亲嘴(男的把女的衣服脱下)

2023-04-27

焦点速讯:朱元璋火烧庆功楼,把功臣全部烧死,这件事是真的吗?

2023-04-27

我是余欢水小说结局_我是余欢水的结局是什么 全球热议

2023-04-27

如何预防下一次传染病大流行

2023-04-27

三年级人教版数学下册第七单元测试_人教版三年级下册数学第七单元试题

2023-04-27

当前视讯!华为Mate50最新售价确定,256GB版本直降1550元,幸福来得很突然

2023-04-27

核酸检测怎么查结果_核酸检测查结果的方法

2023-04-27

金杯汽车去年营收56.31亿元,同比增长8.49%

2023-04-26

立中集团:2022年营业收入增至214亿元 三大核心板块均保持增长

2023-04-26

今年一季度新疆一般公共预算收入557.2亿元 同比增长逾两成

2023-04-26

天天新消息丨海正药业龙虎榜:机构净买入1.28亿元

2023-04-26

全球播报:救世星龙怎么留在场上_救世星龙

2023-04-26

Copyright ©  2015-2022 青年频道网版权所有  备案号:皖ICP备2022009963号-20   联系邮箱:39 60 291 42@qq.com