DDD的优势(2)

简介: DDD的优势(2)

7.5.2 聚合根


聚合根(Aggregate Root)是DDD中的一个概念,是一种更大范围的封装,会把一组有相同生命周期、在业务上不可分割的实体和值对象放在一起,只有根实体可以对外暴露引用,这也是一种内聚性的表现。


确定聚合边界要满足固定规则(Invariant),是指在数据变化时必须保持的一致性规则,具体规则如下。


  • 根实体具有全局标识,最终负责检查规定规则。
  • 聚合内的实体具有本地标识,这些标识在Aggregate内部才是唯一的。
  • 外部对象不能引用除根Entity之外的任何内部对象。
  • 只有Aggregate的根Entity才能直接通过数据库查询获取,其他对象必须通过遍历关联来发现。
  • Aggegate内部的对象可以保持对其他Aggregate根的引用。
  • Aggregate边界内的任何对象在修改时,整个Aggregate的所有固定规则都必须满足。


仍以银行转账的例子来说明,如图7-10所示,账号(Account)是客户信息(CustomerInfo)Entity和值对象(Address)的聚合根,交易(Tansaction)是流水(Journal)的聚合根,流水是因为交易才产生的,具有相同的生命周期。


image.png


7.5.3 领域服务


有些领域中的动作是一些动词,看上去并不属于任何对象。它们代表了领域中的一个重要的行为,所以不能忽略它们或者简单地把它们合并到某个实体或者值对象中。当这样的行为从领域中被识别出来时,推荐的实践方式是将它声明成一个服务。这样的对象不再拥有内置的状态,其作用仅仅是为领域提供相应的功能。Service往往是以一个活动来命名,而不是Entity来命名。


例如在银行转账的例子中,转账(transfer)这个行为是一个非常重要的领域概念,但是它发生在两个账号之间,归属于账号Entity并不合适,因为一个账号Entity没有必要去关联它需要转账的账号Entity。在这种情况下,使用MoneyTransferDomainService就比较合适了。识别领域服务,主要看它是否满足以下3个特征。


(1)服务执行的操作代表了一个领域概念,这个领域概念无法自然地隶属于一个实体或者值对象。


(2)被执行的操作涉及领域中的其他对象。



(3)操作是无状态的。


7.5.4 领域事件


领域事件(Domain Event)是在一个特定领域由一个用户动作触发的,是发生在过去的行为产生的事件,而这个事件是系统中的其他部分或者关联系统感兴趣的。

为什么领域事件如此重要?因为在分布式环境下,很少有业务系统是单体的(Monolithic),消息作为分布式系统间耦合度最低、最健壮、最容易扩展的一种通信机制,是我们实现分布式系统互通的重要手段。关于领域事件,我们需要注意两点,分别是事件命名和事件内容。


1.事件命名


事件是表示发生在过去的事情,所以在命名上推荐使用Domain Name + 动词的过去式 + Event,这样可以更准确地表达业务语义。例如,在银行转账的例子中,对于转账成功和失败我们都需要发出事件通知,可以定义两个领域事件如下。

(1)MoneyTransferedEvent:表示转账成功发出的事件。


(2)MoneyTransferFailedEvent:表示转账失败发出的事件。


2.事件内容


事件内容在计算机术语中叫作payload,有以下两种形式。


(1)自恰(Enrichment):就是在事件的payload中尽量多放数据,这样consumer不需要回查就能处理消息,也就是自恰地处理消息。


(2)回查(Query-Back):这种方式是只在payload放置id属性,然后consumer通过回调的形式获取更多数据。这种形式会加重系统的负载,可能会引起性能问题。


7.5.5 边界上下文


领域实体的意义是有上下文的,比如同样是Apple,在水果店和苹果手机专卖店中表达出的含义就完全不一样。边界上下文(Bounded Context)的作用是限定模型的应用范围,在同一个上下文中,要保证模型在逻辑上统一,而不用考虑它是不是适用于边界之外的情况。


那么不同上下文之间的业务实体要如何实现交互呢?就像关系数据库和对象之间需要ORM一样,不同上下文之间的实体也需要映射。在DDD中,这种机制叫作上下文映射(Context Mapping),我们可以使用防腐层(Anti-Corruption)来完成映射的工作。


如图7-11所示,在我们开发的CRM系统中,商家的客户大部分是来自于ICBU网站的会员,虽然二者有很多属性都是一样的,但我们还是有必要引入防腐层来做上下文映射,主要有以下两个原因。


(1)虽然属性大部分一样,但二者的作用和行为在各自上下文中是不一样的。

(2)解耦影响,加入了防腐层之后,网站的会员变化就不会影响到CRM系统了。


image.png

相关文章
Element ui dialog弹窗最大化最小化关闭组件封装
封装一个最大化最小化关闭的dialog弹窗组件
3284 1
|
4月前
|
存储 人工智能 缓存
别再把大脑当成 /dev/null 了!用这套AI指令给记忆装个 "Redis 缓存层"
本文将大脑记忆比作数据库存储,指出传统记忆的"无索引"缺陷。通过一套"记忆架构师AI指令",利用数据预处理、建立索引和持久化策略(遗忘曲线),帮助开发者构建高效、稳固的知识记忆系统,实现认知的"架构升级"。
655 4
|
人工智能 文字识别 安全
Stirling-PDF:51.4K Star!用Docker部署私有PDF工作站,支持50多种PDF操作,从此告别在线工具
Stirling-PDF 是一款基于 Docker 的本地化 PDF 编辑工具,支持 50 多种 PDF 操作,包括合并、拆分、转换、压缩等,同时提供多语言支持和企业级功能,满足个人和企业用户的多样化需求。
1383 6
Stirling-PDF:51.4K Star!用Docker部署私有PDF工作站,支持50多种PDF操作,从此告别在线工具
|
10月前
|
运维 监控 安全
微信养号最好的方法,有工具吗?步骤是什么
微信养号技术与Python自动化实践 1. 微信养号基础概念与重要性
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能股票交易策略
使用Python实现智能股票交易策略
735 0
|
JSON 数据可视化 数据格式
PIE-engine 教程 ——长时间序列NDVI影像计算和chart时序图加载(2017年锦州全年植被指数展示)
PIE-engine 教程 ——长时间序列NDVI影像计算和chart时序图加载(2017年锦州全年植被指数展示)
871 0
PIE-engine 教程 ——长时间序列NDVI影像计算和chart时序图加载(2017年锦州全年植被指数展示)
|
机器学习/深度学习 算法 搜索推荐
怎样设计一个广告系统
怎样设计一个广告系统
941 0
怎样设计一个广告系统
|
Prometheus 监控 Cloud Native
【云原生监控系列第二篇】Prometheus进阶——PromQL数据类型
【云原生监控系列第二篇】Prometheus进阶——PromQL数据类型
701 0
【云原生监控系列第二篇】Prometheus进阶——PromQL数据类型
|
存储 安全 测试技术
SystemVerilog学习-02-数据类型
SystemVerilog学习-02-数据类型
1665 0
SystemVerilog学习-02-数据类型
|
机器人 Python
ROS中阶笔记(三):机器人仿真—ArbotiX+rviz功能仿真
ROS中阶笔记(三):机器人仿真—ArbotiX+rviz功能仿真
978 0
ROS中阶笔记(三):机器人仿真—ArbotiX+rviz功能仿真

热门文章

最新文章