DDD的基础设施到底在哪里

简介: DDD的基础设施到底在哪里

Eric Evans对常见的三层架构做了优化,形成专属DDD的分层架构,如下图所示:

image.png

Eric对基础设施层(Infrastructure Layer)的定义为:“为上面各层提供通用的技术能力:为应用层传递消息,为领域层提供持久化机制,为用户界面层绘制屏幕组件,等等。基础设施层还能够通过架构框架来支持4个层次间的交互模式。

从DDD的分层架构看,领域层对基础设施层产生了依赖,这违背了依赖倒置原则:上层模块不应该依赖于下层模块,而应该依赖于下层模块的抽象。所以,Vernon在《实现领域驱动设计》中,将上图所示的分层架构修改为下图的结构:

image.png

基础设施层挪到了最上面,领域层没有任何依赖,就能让领域层更加纯粹,不再收到外界变化的影响。然而,事与愿违,领域层依旧有必须依赖基础设施层的理由,例如,领域层的领域服务就必然需要访问数据库,这一功能属于基础设施层的职责。

该如何处理领域层与基础设施层的关系?Eric的解决方式是引入Repository模式。他选择将Repository的接口放到领域层,实现放到基础设施层。如此一来,领域服务对Repository接口的调用就属于同层之间的依赖,而实现则交给了依赖注入,由其在运行时将实现逻辑绑定到领域服务,如此就解除了领域层与基础设施层的耦合。

如果将Repository对领域对象的操作视为对对象集合的操作,将Repository放到领域层也就顺理成章了。可是对于一个业务系统而言,领域层不仅仅需要访问数据库,如果需要访问消息队列传递消息呢,需要访问文件呢,需要网络通信呢?难道要将所有访问外部资源的接口都归属到领域层吗?这明显不合理。

Eric提出分层架构的主要目的是为了分离领域层,实现业务和技术的正交。实现该目标的最佳途经莫过于分离基础设施层的接口与实现,如此也恰好满足依赖倒置原则。菱形对称架构的南向网关之所以分为端口和适配器,原因就在此。

image.png

逻辑上,端口和领域层彼此分离,但由于二者存在双向依赖,在物理上,需要它们部署在一起。而适配器和端口则可以分开,以满足接口与实现分离的设计要求。

按照Eric对基础设施层的定义,北向网关的远程服务也属于基础设施的一种。分层架构的应用层对应于北向网关的本地服务层。菱形对称模式彻底改变了DDD分层架构的定义,更接近整洁架构和六边形架构,属于内外分层的表现形式。

菱形对称架构也可体现为分层架构形式:

image.png

菱形对称架构是为DDD的限界上下文量身定做。由于限界上下文是业务能力的纵向切分,在其边界内,不仅包含领域层,也包含了网关层,甚至其逻辑边界还包含它要访问的数据库。若回到基础设施的语义,也就认为限界上下文包含基础设施层。

倘若基础设施只为当前限界上下文服务也就罢了,一旦有别的限界上下文也需要调用,又该如何处理?

在讨论此问题之前,有必要明确DDD的基础设施层究竟包含哪些内容。注意,DDD的基础设施并不等同于云计算IaaS层对应的基础设施,它是一种隐喻,代表了支撑领域逻辑的基础功能,同样由当前开发团队编码实现,通常用于封装对外部资源的访问。

常见的外部资源包括:

  • 数据库
  • 缓存
  • 设备
  • 外部接口
  • 消息队列

由于访问基础设施的调用者是领域层,因此,不要将操作外部资源的框架与其混为一谈。这一定义与Eric对基础设施层的定义略有不同,但我认为才是正解。

以订单上下文为例。南向网关访问数据库的基础设施可以是OrderRepository端口和适配器,但它显然不是Hibernate或MyBatis这样的ORM框架;访问Kafka的基础设施可以是OrderPlacedPublisher端口和适配器,而不是spring-kafka框架;至于对上游限界上下文的访问,更是如此,不必多说。

弄清楚二者的区别,就可以深刻理解到:一个限界上下文内部的基础设施,往往带有当前限界上下文的业务含义,是相对专有的,实际上,很少存在跨限界上下文复用的可能。

一种特殊场景是Context Map的防腐层模式,它在菱形对称架构中体现为Client端口,用于封装对上游限界上下文或伴生系统外部接口的访问。如果上游限界上下文的北向网关服务会被多个下游访问,又需要引入防腐层隔离上游的变化,就存在多个限界上下文防腐层实现的重复。

为避免重复,常见的做法是将该防腐层升级为一个专有的限界上下文。一个典型例子是支付限界上下文。在电商系统中,支付系统属于目标系统之外的伴生系统。支付订单、发起退款,缴纳会员费等多个业务场景都需要调用支付系统。如果分别为其实现防腐层,就会在订单上下文、售后上下文与会员上下文中,散落着重复的支付适配逻辑,解决办法就是专门为其定义一个支付上下文。

我曾提到过,对于一个规模相对较大的目标系统而言,架构要考虑两个层次:

  • 系统上下文
  • 限界上下文

目前,限界上下文的基础设施问题已经给予澄清,那么,在系统层次,又该如何考虑?

由于限界上下文是业务能力的纵向切分,一个自治的限界上下文,就必须包含它所需要的完整的内容,如果将每个限界上下文都看做是一个独立的子系统,在系统层次似乎就没有基础设施的必要了。

我正是这般认为的,但恐怕一些人并不怎么认为。之所以存在分歧,是因为我们对基础设施的定义并未达成一致。

譬如说,有人认为,用户管理、组织管理与权限认证属于整个系统的基础设施;我却认为它们应该属于映射到通用子领域的限界上下文,在系统架构中,位于分层架构的基础层:

image.png

又有人认为,诸如Spring Cloud、Hibernate、Seata、Dubbo之类的框架属于整个系统都需要的基础设施,故而需要定义专门的基础设施层。如前所述,我认为它们并非DDD分层架构的基础设施层。

这里牵涉到对架构视图的理解。无论是DDD分层架构,还是我提出的系统分层架构与菱形对称架构,都属于应用逻辑架构的一部分。系统需要使用的框架根本就不在应用架构的范围内。如果要在架构中体现它们,应该放到技术架构。若要了解架构视图的详细内容,可以参考阅读我的系列文章《全面探索架构师图

最后,呼应标题。

DDD分层架构的基础设施并非技术架构中的框架或平台,而是限界上下文领域层需要调用的端口或适配器,它们位于限界上下文内部的南向网关,又或者基于复用的必要,被抽离出来形成单独的限界上下文。为避免与云平台或其他基础架构提及的基础设施混淆,我建议慎用这一术语。若要使用,需先明确其真正的含义,了解它包含的实际内容。

END

相关文章
|
缓存 前端开发 中间件
DDD 领域驱动设计落地实践系列:工程结构分层设计
前面几篇文章中,笔者给大家阐述了 DDD 领域驱动设计的三大过程,重点围绕如何通过战略设计与战术设计进行 DDD 落地实践进行了详细的讨论,但是还没有涉及到工程层面的落地。实际上所有的这些架构理论到最后都是为了使得我们代码结构更加清晰,从而开发出 bug 少、扩展性强、逻辑清楚的应用。因此本文就是为了解决 DDD 领域驱动落地实践最后一公里问题,将我们分析出来的领域模型通过与工程结构的映射实现真正的落地。
DDD 领域驱动设计落地实践系列:工程结构分层设计
|
Java 测试技术 API
Java RESTful中的PATCH请求:局部更新与资源修改
在RESTful架构中,PATCH请求是一种用于局部更新已有资源的操作。PATCH请求允许客户端将部分数据发送到服务器,以便对资源进行局部修改,而不必替换整个资源。本文将引导您深入了解Java中使用PATCH请求构建RESTful API,探讨其特点、实现方式、用例以及在实际应用中的优势。
|
10月前
|
人工智能 自然语言处理 数据安全/隐私保护
企业AI落地开源五剑客:Open-WebUI、Dify、RAGFlow、FastGPT、n8n
在AI技术迅猛发展的今天,企业常面临数据安全、技术门槛和系统整合等难题。本文介绍了五款开源工具——Open WebUI、Dify、RAGFlow、FastGPT和n8n,它们以低成本、私有化部署和模块化扩展的优势,助力企业构建AI能力闭环,覆盖交互、生成、知识处理与流程自动化等多个环节,推动AI真正落地应用。
|
Android开发 C++
【Android 逆向】IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )
【Android 逆向】IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )
1739 0
【Android 逆向】IDA 工具使用 ( IDA 32 位 / 64 位 版本 | 汇编代码视图 IDA View-A | 字符串窗口 Strings window )
|
人工智能 前端开发 Java
DDD四层架构和MVC三层架构的个人理解和学习笔记
领域驱动设计(DDD)是一种以业务为核心的设计方法,与传统MVC架构不同,DDD将业务逻辑拆分为应用层和领域层,更关注业务领域而非数据库设计。其四层架构包括:Interface(接口层)、Application(应用层)、Domain(领域层)和Infrastructure(基础层)。各层职责分明,避免跨层调用,确保业务逻辑清晰。代码实现中,通过DTO、Entity、DO等对象的转换,结合ProtoBuf协议,完成请求与响应的处理流程。为提高复用性,实际项目中可增加Common层存放公共依赖。DDD强调从业务出发设计软件,适应复杂业务场景,是微服务架构的重要设计思想。
|
JSON 前端开发 测试技术
2025年 5 个好用的 Socket.IO 调试工具推荐
在实时通信应用开发中,Socket.IO 是一个非常流行的框架,但调试其应用可能较为棘手。为此,推荐5个好用的 Socket.IO 调试工具:Apifox、WebSocket King、Socket.IO Test Client、Socket.IO Inspector 和 Postman。其中,Apifox 集成设计、调试、测试和文档生成于一体,支持多种版本的 Socket.IO 客户端,提供强大的接口管理和团队协作功能;
|
存储 消息中间件 JSON
DDD基础教程:一文带你读懂DDD分层架构
DDD基础教程:一文带你读懂DDD分层架构
|
消息中间件 供应链 测试技术
图解 DDD,这一篇总结太全面了!
DDD领域驱动是非常热的架构设计,微服务也有大量涉及,本文详细解析领域驱动设计(DDD),涵盖DDD原理、实践步骤及核心概念等,帮助更好地管理复杂业务逻辑。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
图解 DDD,这一篇总结太全面了!
|
消息中间件 存储 监控
消息中间件第八讲:消息队列 RocketMQ 版实战、集群及原理
消息中间件第八讲:消息队列 RocketMQ 版实战、集群及原理
1047 0
|
消息中间件 测试技术 领域建模
DDD - 一文读懂DDD领域驱动设计
DDD - 一文读懂DDD领域驱动设计
50906 6

热门文章

最新文章