在实践中,需要保证值对象创建后就不能被修改,即不允许外部再修改其属性(如:在订单上下文中如果你只关注下单时商品信息快照,那么将商品对象视为值对象是很好的选择)
聚合
聚合(Aggregate)是一组相关对象的集合,作为一个整体被外界访问,它由 实体 和 值对象 在 一致性边界之内 组成,聚合根(Aggregate Root)是这个聚合的根节点。
聚合的设计原则
在设计聚合时,我们需要慎重的考虑 一致性
关注聚合的 一致性边界,在一致性边界之内建模真正的 不变条件(不变条件 指的是业务规则)
同一个事务之内不能修改多个 聚合实例
在边界之外使用 最终一致性
设计 小聚合;(“小” 的极端意思是指 一个聚合只拥有全局标识和单个属性;这种做法不推荐)
通过唯一标识来引用其他聚合或实体:当存在对象之间的关联时,建议引用其唯一标识而非引用其整体对象(如果是外部上下文中的实体,引用其唯一标识或将需要的属性构造值对象)
注:如果聚合创建复杂,推荐使用 工厂方法 来屏蔽内部复杂的创建逻辑
领域服务
当领域中的某个操作过程或转换过程不是实体或者值对象的职责时,将该操作放在一个单独的接口中,即 领域服务。
领域服务的特点
领域服务 和通用语言一致,表示 无状态 的操作,它用于实现特定于某个领域的任务;
某个操作不适合放在实体(聚合)与值对象上时,适合 领域服务;
执行一个显著的业务操作过程;
对领域对象进行转换;
以多个领域对象作为输入进行计算,结果产生一个值对象;
领域服务 是用来处理业务逻辑的(我们不能将业务逻辑放到应用层,即使非常简单,它依然是业务逻辑)
领域事件
对 领域中 所发生的事件(领域专家所关心的发生在领域中的一些事件)进行建模,即 领域事件(领域模型 的组成部分)
领域事件的特点
领域事件 用来捕获领域中发生的一些事情,开始使用领域事件时,要 对不同的事件进行定义;
“当...时,请通知我” 等等场景
领域事件发布方法
限界上下文内,观察者模式 是一种简单高效的发布领域事件的方法;
限界上下文外,利用 消息机制 将本地限界上下文产生的事件发送到 远程限界上下文 中(我们要保证 所有限界上下文 的最终一致性);
资源库
对领域的存储和访问进行统一管理的对象,即 资源库(Repository);
资源库的特点
通常我们将 聚合实例 存放在资源库中,之后再通过资源库获取相同的实例;
通常来说,聚合类型 和 资源库之间存在着 一对一的关系;
当两个或多个聚合位于同一个对象层级中时,他们可以共享同一个资源库;
注:资源库和 DAO是不同的,一个DAO主要从数据库表的角度来看待问题,并且提供 CRUD 操作
DDD之架构极简化架构设计主要从下边三个角度出发:
业务架构:根据业务需求设计业务模块及交互关系;
系统架构:根据业务需求设计系统和子系统的模块;
技术架构:根据业务需求决定采用的技术及框架;
DDD的核心诉求 就是能够让 业务架构 和 系统架构 形成绑定关系,从而当我们去响应 业务变化 调整业务架构时,系统架构的改变是随之自发的
这个 业务变化 的结果有两个:
业务架构 的梳理和 系统架构 的梳理是同步渐进的,其结果是划分出的 业务上下文 和 系统模块结构 是绑定的;
技术架构 是解耦的,可以根据划分出来的业务上下文的系统架构选择最合适的实现技术;
架构类型 分层架构
所有架构的始祖,支持N层架构系统,将一个应用程序或者系统分为不同的层次
DDD使用的传统分层架构:
分层架构原则:每层只能与其下方的层发生耦合(分层架构 分为 严格分层架构 和 松散分层架构)。
严格分层架构:每层只能和直接位于其下方的层发生耦合。
松散分层架构:任意上方层与任意下方层发生耦合。
六边形架构六边形结构(端口与适配器架构、onion架构):一种具有对称性特征的架构风格。
为什么是6边形?不是4边形或8边形?