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

这篇具有很好参考价值的文章主要介绍了关于聚合根,领域事件的那点事---深入浅出理解DDD。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:京东物流 赵勇萍

前言

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

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

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

一个简单的demo业务场景

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

1. 实体:

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

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

2. 值对象:

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

3. 领域事件:

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

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

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

4. 聚合根:

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

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

5. 对外接口服务:

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

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

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

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

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

demo的java代码实现

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

  1. 商品实体类:
// 省略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中,领域事件通常由三个部分组成:

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

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

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

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

总之,领域事件是DDD架构中非常重要的概念,它可以帮助我们更好地理解业务过程,设计出更加符合实际需求的系统,并提高系统的可维护性和可扩展性。文章来源地址https://www.toymoban.com/news/detail-427063.html

到了这里,关于关于聚合根,领域事件的那点事---深入浅出理解DDD的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • less预处理语言的运用之-变量拼接那点事

    less语法的技巧总结,很基础,熟练掌握后能提高我们在大型项目中的开发效率 递归 less连接符与import 关注我的个人公众号,获取更多前后端开发经验知识

    2024年02月16日
    浏览(75)
  • 软件工程:帕金森定律,项目工期的那点事儿

    hi,我是熵减,见字如面。 在软件开发中,你是否遇到过这种情况: 团队要开发一个简单的购物车应用,项目预期时间是2周工期。负责开发的工程师默认利用完整的2周时间来完成任务。在第一周,工程师会认为任务很轻松,有充足的时间来完成任务,所以会采取气定神闲的

    2023年04月17日
    浏览(41)
  • Bootstrap.yml那点事 Spring Cloud 配置中心多环境配置

    加载顺序 若application.yml 和bootstrap.yml 在同一目录下:bootstrap.yml 先加载 application.yml后加载,bootstrap.yml 用于应用程序上下文的引导阶段。bootstrap.yml 由父Spring ApplicationContext加载。 配置区别 bootstrap是spring cloud的配置上下文加载。由spring-cloud-context包加载。引入依赖 具体加载类

    2023年04月08日
    浏览(53)
  • 开发那点事(十六)从零开始搭建一个NFT数字藏品平台

    写在前面的话 从6月初到七月研究了将近一个月NFT 区块链这方面的东西,从啥都不会到了解原理,总算是有点成果了,在这里分享给大家。 核心大纲 百度超级链开放网络(Solidity语言) 集成openzeppelin中的ERC721合约快速完成合约开发 Springboot 作为后台开发语言调用线上合约 通

    2024年01月16日
    浏览(56)
  • 关于《樱花映射(Sakura Frp)开服务器的那件事》的教程

    樱花映射~~~免费-穿,轻松-透~~~ 打住!我不是来打广告的! 只是很多小伙伴,在面临服务器的对外开放时,遇到挺多麻烦事,不知道如何来解决公网ip的问题 解决方法是有的,很多,而且还要花钱。😒 办法一:如果是在家想开一个服务器,和小伙伴们联机游玩一些游戏时,

    2024年02月05日
    浏览(39)
  • 深入浅出关于go web的请求路由

    最近重新接触Go语言以及对应框架,想借此机会深入下对应部分。 并分享一下最近学的过程很喜欢的一句话: The limits of my language mean the limits of my world. by Ludwig Wittgenstein 我的语言之局限,即我的世界之局限。 首先来介绍一下什么是路由。 路由是指确定请求应该由哪个处理程

    2024年01月19日
    浏览(80)
  • DDD进阶_领域事件是什么?如何开展领域事件驱动开发工作?

    DDD从入门到精通,系列文章传送地址,请点击本链接。   目录 一、什么是领域事件 二、如何识别领域事件 三、领域事件的数据一致性 四、领域事件分类 1、微服务内的领域事件 2、微服务之间的领域事件 五、领域事件案例 六、领域事件总体架构图 1. 事件构建和发布 2、事

    2024年02月15日
    浏览(40)
  • 【Prism系列】Prism事件聚合器

    我们知道MVVM指的就是Model ViewModel 与 View,之前为了做到业务逻辑和前台彻底分离,我们使用了Command命令,将界面的的输入或者是某些控件的事件,转化为命令。这样业务逻辑就从View搬到了ViewModel。很明显这个传递方向是View -》ViewModel。         但是现在有个一个需求是需要

    2024年02月06日
    浏览(42)
  • 05.领域驱动设计:掌握领域事件,解耦微服务的关键

    目录 1、概述 2、领域事件 2.1 如何识别领域事件 1.微服务内的领域事件 2.微服务之间的领域事件 3、领域事件总体架构 3.1 事件构建和发布 3.2 事件数据持久化 3.3 事件总线 (EventBus) 3.4 消息中间件 3.5 事件接收和处理 4、案例 5、总结 1、概述 在事件风暴(Event Storming)时,我们

    2024年02月22日
    浏览(47)
  • 高德地图api2.0点聚合及点标记事件

    在使用高德地图API的过程中,发现2.0版本的点聚合和之前版本的使用上有很大的区别,在此做一下点聚合的使用以及点标记的事件的记录。 在2.0之前的版本,MarkerClusterer插件的使用如下: 而2.0版本对MarkerClusterer进行了改动 在2.0版本中,markerClusterOptions去掉了minClusterSize 集合

    2024年02月13日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包