01. 基础概念
元模型

在
-
战术设计
(Tactic DDD) :Entity, Value Object; Aggregate, Root Entity, Service, Domain Event; Factory, Repository。 -
战略设计
(Strategic DDD) :Bounded Context, Context Map; Published Language, Shared Kernel, Open Host Service, Customer-Supplier, Conformist, Anti Corruption Layer (context relationship types)。

领域驱动设计围绕着领域模型进行设计,通过分层架构(Layered Architecture)将领域独立出来。表示领域模型的对象包括:实体、值对象和领域服务,领域逻辑都应该封装在这些对象中。这一严格的设计原则可以避免业务逻辑渗透到领域层之外,导致技术实现与业务逻辑的混淆。在领域驱动设计的演进中,又引入了领域事件来丰富领域模型。聚合是一种边界,它可以封装一到多个实体与值对象,并维持该边界范围之内的业务完整性。在聚合中,至少包含一个实体,且只有实体才能作为聚合根(Aggregate Root
工厂和资源库都是对领域对象生命周期的管理。前者负责领域对象的创建,往往用于封装复杂或者可能变化的创建逻辑;后者则负责从存放资源的位置(数据库、内存或者其他

战术设计
实体与值对象
每个实体是具有唯一标识的领域概念,并且可以相当长的一段时间内持续地变化。值对象则是通过对象属性值来识别的对象,它将多个相关属性组合为一个概念整体。在
关于实体与值对象的详细讨论参阅领域对象。
Aggregate(聚合)与Aggregate Root (聚合根)
聚合是具有一定关联关系的实体对象的集合,用来划分实体之间的边界,使模型之间更加内聚,边界更加清晰,定义清晰的聚合有助于避免混乱的模型关系划分导致模型之间错综复杂的关系网。抛除概念,可以理解为一组有关联关系的数据单元,聚合的加载、修改、销毁作为一个整体进行。聚合中所包含的对象之间具有密不可分的联系,一个聚合中可以包含多个实体和值对象,因此聚合也被称为根实体。聚合是持久化的基本单位,它和资源库具有一一对应的关系。
而聚合根是聚合的边界,是与外部打交道的唯一入口,聚合内部实体对象或值对象保持被聚合根引用,不可被其他聚合操作引用,也不能单独进行查询。聚合根是一种更大范围的封装,把一组有相同生命周期、在业务上不可分隔的实体和值对象放在一起考虑,只有根实体可以对外暴露引用,也是一种内聚性的表现。聚合内部的实体也有可能引用其他的聚合根。由此特性可得,聚合根的查询,在
比如“公司”
聚合根(Aggregate Root)是
- 根实体具有全局标识,最终负责检查规定规则
- 聚合内的实体具有本地标识,这些标识在
Aggregate 内部才是唯一的 - 外部对象不能引用除根
Entity 之外的任何内部对象 - 只有
Aggregate 的根Entity 才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现 Aggegate 内部的对象可以保持对其他Aggregate 根的引用Aggregate 边界内的任何对象修改时,整个Aggregate 的所有固定规则都必须满足
还是看银行的例子,Account(账号)是

聚合根是一个逻辑概念,主观性很强,所以在建模过程中很容易产生分歧,因此在日常工作中千万不要教条,把握住一条主要原则,我们的最终目的是为了业务语义显现化,如果因为聚合根把模型弄的晦涩难懂那就得不偿失了。
Service(领域服务)
建模一个领域概念,把它放在实体上不合适,它放在值对象上也不合适,或者碰到跨聚合实例业务逻辑,没办法合理放到某个实体中的业务逻辑,领域服务就是应对这些情况的服务。如果勉强地把这些重要的领域功能归为
在分层架构中需要区分什么时候应该定义领域服务,什么时候应该定义应用服务,一个根本的判断依据是看需要封装的职责是否与领域相关。
工厂(Factory)
有时候创建领域对象不仅仅是简单的
仓储(Repository)
由于聚合的特性,我们需要一并加载聚合实体到内存,也需将聚合整体持久化到
抛除概念,从实际开发角度,仓储是领域模型与
如果系统并非用
Domain Event(领域事件)
在
战略设计
领域驱动设计的战略设计阶段是从以下两个方面来考虑的:
- 问题域方面:针对问题域,引入限界上下文(Bounded Context)和上下文映射(Context Map)对问题域进行合理的分解,识别出核心领域(Core Domain)与子领域(SubDomain
) ,并确定领域的边界以及它们之间的关系,维持模型的完整性。 - 架构方面:通过分层架构来隔离关注点,尤其是将领域实现独立出来,能够更利于领域模型的单一性与稳定性;引入六边形架构可以清晰地表达领域与技术基础设施的边界;
CQRS 模式则分离了查询场景和命令场景,针对不同场景选择使用同步或异步操作,来提高架构的低延迟性与高并发能力
Bounded Context(限界上下文)
用来封装通用语言和领域对象,为领域提供上下文语境,保证在领域之内的一些术语、业务相关对象等(通用语言)有一个确切的含义,没有二义性。使团队所有成员能够明确地知道什么必须保持一致,什么必须独立开发。
领域实体是有边界上下文的,比如
所以边界上下文(Bounded Context)在
上下文映射(Context Mapping)
不同

事件风暴(Event Storming)
事件风暴是一项团队活动,旨在通过领域事件识别出聚合根,进而划分微服务的限界上下文。在活动中,团队先通过头脑风暴的形式罗列出领域中所有的领域事件,整合之后形成最终的领域事件集合,然后对于每一个事件,标注出导致该事件的命令(Command
领域状态
在软件设计领域经常会提到状态(State)这个词,而服务之间的状态本质上体现的还是一种数据关系。如果一个数据需要在多个服务之间共享才能完成一项业务功能,那么这项业务功能就被称为有状态。基于这项业务功能所设计和实现的一系列服务之间就形成了一种状态性,这一系列服务就是有状态服务。
很多服务都会把自己的状态下沉到一个庞大的共享数据库中,这也是一些传统
共享内核(Shared Kernel)
如何实现不同域之间的协作,同时又要保证各自领域的概念的完整性是有一套方法论的。总体来说,大概有两种方式:共享内核(Shared Kernel)和防腐层(ACL,Anti-Corruption Layer
It’s possible that only one of the teams will maintain the code, build, and test for what is shared. A Shared Kernel is often very difficult to conceive in the first place, and difficult to maintain, because you must have open communication between teams and constant agreement on what constitutes the model to be shared.

其优点是
防腐层(ACL,Anti-Corruption Layer)
An Anticorruption Layer is the most defensive Context Mapping relationship, where the downstream team creates a translation layer between its Ubiquitous Language (model) and the Ubiquitous Language (model) that is upstream to it.

防腐层是隔离最彻底的做法,其优点是没有
Whenever possible, you should try to create an Anticorruption Layer between your downstream model and an upstream integration model, so that you can produce model concepts on your side of the integration that specifically fit your business needs and that keep you completely isolated from foreign concepts.
Links
- https://zhuanlan.zhihu.com/p/381540329 深入理解领域驱动设计中的聚合