概念
关键词:战略设计、战术设计、领域驱动、数据驱动、领域模型、领域对象、值对象、聚合、聚合根、领域、子域、核心域、通用域、支撑域、领域服务、应用服务、事件风暴
什么是DDD
DDD领域驱动不是架构,而是一种架构设计方法论。
在当今以微服务为主流的环境下,很多时候我们在拆分微服务的时候,往往是根据直觉、经验对服务进行拆分,比如订单服务、用户服务、支付服务。
但这些服务只是将传统的单体架构拆分为了多个单体架构,当某一个服务的业务经过长期发展,业务越来越负责,代码越来越臃肿。
当服务中的某些核心业务性能出现瓶颈的时候,基于微服务的理念,可能需要将出现瓶颈的业务抽取为单独的服务进行水平扩展。
这时我们发现,代码和业务都过于耦合,同一个服务中的业务之间边界不清晰,拆分成本很高。如果基于整个服务进行水平扩展,对服务器的资源浪费又比较严重,这就不利于架构的演进。
上面只是我们在微服务架构中遇到的众多问题中的一种,直到DDD的出现,通过领域建模,划分领域边界,再根据这些领域边界划分微服务,很好的贯彻了“高内聚、低耦合”的思想,它能指导我们设计出清晰的领域和应用边界,帮助我们更容易的实现架构演进。
战略设计和战术设计
战略设计: 主要从业务角度出发,建立业务领域模型,划分领域边界
战术设计: 主要从技术角度出发,侧重于领域模型的技术实现,比如代码如何分层,包括聚合根、实体、值对象、领域服务、应用服务等代码逻辑的实现
设计聚合
我们以电商的创建订单场景为例,简单对业务进行分析,并落实到DDD的各个概念:
- 采用事件风暴,根据业务行为,梳理出所有创建订单的实体和值对象,比如:用户、商户、商品、订单、购物车等等
- 找出聚合根,判断一个实体是不是聚合根,可以分析是否符合这些要素:
- 独立的生命周期
- 全局唯一ID
- 可创建和修改其它对象
- 有专门的模块管理这个实体
- 根据业务单一职责和高内聚原则,找出和聚合根关联密切的所有实体和值对象,构建出1个包含聚合根(唯一)、多个实体和值对象的集合,这个集合就是聚合。这里我们可以构建出订单、用户、商户、商品、购物车四个聚合。
- 分析聚合之间的关系,画出对象引用和依赖模型。创建订单,需要有收件人信息和收货地址,订单在创建后这两个信息不会因为用户后续更新数据而发生更新,所以将用户信息、收货地址作为订单聚合的值对象。同理,商品信息也一样,商品和商户是独立但又紧密联系的,两者结合作为订单的值对象。一个订单中可能包含多个商户的商品,多个商户的商品属于同一个订单,但是在商户端不同商户间的订单又是隔离的,所以这里有商户订单和用户订单两个对象。其中购物车和创建订单没有直接关系,创建订单成功时,会触发领域事件“更新购物车”。
上面的分析可能不合理,只是作为DDD领域分析的一个例子
重要概念
实体
领域模型中的实体以DO(领域对象)的形式存在,每个实体对象都有一个唯一的ID,它具有业务属性和业务行为。
在代码中,实体类包含属性和方法,通过这些方法实现自身的业务,实体通常采用充血模型,与这个实体相关的所有业务逻辑都在实体的方法中实现。
值对象
通过对象属性值来识别的对象,它将多个相关属性组合为一个实体。它是只读的,不可变的。
聚合
聚合就是由业务和逻辑紧密联系的实体和值对象组合而成,它来协调实体和值对象协同工作,保证它们实现共同的业务逻辑,保证数据一致性。
在DDD领域分层中聚合属于领域层,领域层包含多个聚合,共同实现核心业务逻辑。
如果业务需要同一个聚合内的两个实体共同实现,我们可以用领域服务实现。
如果业务需要两个聚合共同实现,我们可以用应用服务来组合两个聚合实现。
聚合根
聚合根也是实体,它是聚合的管理者。它拥有实体的属性和业务行为。
作为聚合的管理者,它可以协调聚合内的所有实体和值对象,按照固定的规则协同完成业务逻辑。
实体、值对象、聚合根的区别
聚合根也是实体,有全局唯一标识,生命周期属于其所属的聚合。
实体在聚合内部有唯一标识,它的生命周期归聚合根管理,数据可变。
值对象没有唯一标识,生命周期归聚合根管理,数据只读。
聚合根和聚合根之间通过ID关联。
聚合根和其内部的实体,直接对象引用。
聚合根和其内部值对象,直接对象引用。