
一张图看懂DDD+CQRS架构
一张图看懂DDD+CQRS架构
今天我要用 一张图讲清楚DDD+CQRS架构,看懂这张图,DDD就学会了。不废话,直接上图:

DDD是什么
DDD的全称是领域驱动设计 Domain Driven Design,是广泛应用于系统架构设计的一种方法论。
目前业界对DDD的态度实际上褒贬不一,有些人觉得很牛,有些人觉得一文不值。但据我观察,持否定态度的人多数是半懂不懂,只是听别人说“很复杂”,自己往往说不出个所以然来。当然也确实有一些大牛分析到,DDD应用在中小型项目中会显得有些臃肿,这我是认可的,但遗憾的是我也并未看到有人提供了更优解。
我本人并不是DDD的狂热拥趸,只是它确实给了我一种解决问题的思路,并且我认为行之有效。但若你有更好的解决方案,我也十分愿意请教。
提示
如果你对DDD一知半解,我另外有一篇文章《三句话说清DDD的思想内核》,希望能带你入门
这张图我是反反复复推敲了好几年,也参考了许多业界大佬的思路,最终形成此图。
接下来我们沿着这张图,来聊一聊DDD的分层架构,你会看到这其中的设计十分巧妙。
分层解析
基础设施层
基础设施层 infrastructure 处在架构的最外围,这一层与业务规则完全无关。
- 通用能力和技术框架严格来说是可以不放在这一层的,完全可以放到单独的技术框架中
- 入口网关负责协议转换,把外部请求转化为标准的内部接口进行调用,例如controller就是把HTTP(S)请求转为内部请求。如果技术框架做得好,这一层其实也可以没有,例如dubbo框架就是把协议转换包装在框架内部
- 出口网关负责把系统对外的调用进行包装,包括对数据库、缓存、消息队列、下游系统等
基础设施层就像是城堡的城墙,把城堡围与外部隔开,入口网关、出口网关就是城堡的大门
接口定义层
接口定义层 interface layer只定义接口不实现,这里用到的是facade模式,统一把系统对外的服务包装成接口
我这里借鉴了CQRS架构模式(Command Query Responsibility Segregation),把facade api和query api分开,除了可以做读写分离以外,更重要的原因是有些业务的查询特别复杂,例如电商业务,用户打开一个页面除了要查询商品,还要查优惠券、推荐、关系链等,这时候把Command和Query分开是很好的选择。
Query请求是不需要经过应用服务层的,可以直接查询数据库、缓存等。
应用层
也叫应用服务层 Application Service
- 职责1:实现
facade api,这样系统才能提供完整服务。
提示
facade接口定义是与用例分析密切相关的,可以参考《为什么说用例设计在软件开发中很重要》
- 职责2:负责组装领域层的服务,这一层只做编排,不写业务逻辑
提示
不写业务逻辑的意思是:不做逻辑判断、不做数值计算、没有业务规则
职责3:负责调用出口网关,调用出口网关需通过防腐层(ACL Anti-Corruption Layer) 接口,ACL是为了避免外部系统的变更对业务代码直接产生影响(例如缓存组件升级、下游接口升级等)。注意ACL是在应用层定义,并由出口网关来实现,这里用到一个控制反转(IoC Inversion of Control)
职责4:负责事务管理。开启事务、提交事务、回滚事务等
领域层
领域层Domain Layer包含了核心的业务规则,大致上又能分为这几个部分
- 领域服务:通常领域服务也是只做编排尽量不写业务逻辑,领域服务编排的是聚合、工厂和事件。
领域服务对应的是《为什么说用例设计在软件开发中很重要》这篇文章中的二级、三级用例。
另外很多人反感Java代码每一层都要定义接口和实现,即便实现类永远只有一个。我同样也反感。所以人是要变通的,interface层的接口是为了做内外隔离,是必须的,而Domain Service定义接口则完全没必要
- 领域事件:一个事件表示一个任务或一个用例执行完成,通过事件的方式可以进行解耦
- 工厂:负责创建实体
- 仓储:负责存储和加载实体。这里的仓储层只有接口定义,实现放在出口网关,也用到控制反转
- 实体:有唯一标识的充血对象,大部分业务逻辑都写在这里
- 值对象:与实体的区别是,值对象不可变,且没有唯一标识
- 聚合:有些实体之间是有关联性的,把具有强关联关系的实体定义到一个聚合内,可以让业务逻辑更加内聚
还有一个相对特殊的是types,由于值对象是定义在领域层,按照规范,facade api是不能直接依赖领域层的,但又有部分值对象或枚举值很通用,为了简化代码,可以把这些相对通用的类型放在types里面。
总结
这篇文章先简要概括了DDD的分层架构,以及每一层的职责。篇幅原因没有讲每一层的设计原则和设计范式,后续还会再详细说明。
我知道大家很关心是否有demo代码可以参考。有!不仅有示例代码,还有配套的框架和文档!
感兴趣的看这里: 《我用AI+DDD开了一个包子铺》