DDD领域驱动设计实战-分层架构及代码目录结构(上)

简介: DDD领域驱动设计实战-分层架构及代码目录结构

代码结构

DDD并没有给出标准的代码模型,不同的人可能会有不同理解。

按DDD分层架构的分层职责定义,在代码模型里分别为用户接口层、应用层、领域层和基础层,建立了 interfaces、application、domain 和 infrastructure 四个一级目录。

image.png

1 DDD分层架构

1.1 分层架构的基本原则

每层只与位于其下方的层发生耦合。

1.2 分层架构的分类

严格分层架构(Strict Layers Architecture)

某层只能与其直接下层耦合,即我的奴隶的奴隶,不是我的奴隶。

松散分层架构(Relaxed Layers Architecture)

允许任意上层与任意下层耦合。由于用户接口层和应用服务通常需要与基础设施打交道,许多系统都是该架构。


较低层有时也可与较高层耦合,但只限于采用观察者 (Observer)模式或者调停者(Mediator)模式场景。

较低层绝不能直接访问较高层。例如,在使用调停者模式时,较高层可能实现了较低层的接口,然后将实现对象作为参数传递到较低层。当较低层调用该实现时, 它并不知道实现出自何处。

1.3 分层架构演进

1.3.1 传统四层架构

image.png

将领域模型和业务逻辑分离出来,并减少对基础设施、用户界面甚至应用层逻辑的依赖,因为它们不属业务逻辑。将一个夏杂的系统分为不同的层,每层都应该具有良好的内聚性,并且只依赖于比其自身更低的层。


传统分层架构的基础设施层位于底层,持久化和消息机制便位于该层。

这里的消息包含


MQ消息

SMTP

文本消息(SMS)

可将基础设施层中所有组件看作应用程序的低层服务,较高层与该层发生耦合以复用技术基础设施。即便如此,依然应避免核心的领域模型对象与基础设施层直接耦合。

1.3.2 改良版四层架构

传统架构的缺陷

DDD初创开发团队发现,将基础设施层放在最底层存在缺点,比如此时领域层中的一些技术实现就很困难:

  • 违背分层架构的基本原则
  • 难以编写测试用例

何解?

使用依赖反转设计原则:低层服务(如基础设施层)应依赖高层组件(比如用户界面层、应用层和领域层)所提供的接口。

应用依赖反转原则

  • 依赖反转原则后的分层方式:基础设施层在最上方,可实现所有其他层中定义的接口
  • image.png
  • 依赖反转原则真的可以支持所有层吗?

有人认为依赖反转原则中只存在两层:最上方和最下方,上层实现下层定义的抽象接口。因此上图的基础设施层将位于最上方,而用户接口层、应用层和领域层应作同层且都位于下方。对此大家可保留自己意见。

2 各层职责

2.1 Interfaces(用户接口层)

一般包括用户接口、Web 服务等。

只处理用户显示和用户请求,不应包含领域或业务逻辑。

有人认为,既然用户接口需验证用户输入,就无可避免应该包含业务逻辑。事实上,用户接口所进行的验证和对领域模型的验证不同:对那些粗制滥造且只面向领域模型的验证行为,应该予以限制。


如果用户接口使用了领域模型中的对象,那么此时领域对象仅限于数据渲染展现。在采用这种方式时,可使用展现模型对用户接口与领域对象进行解耦。

由于用户可能是人,也可能是其他系统,有时用户接口层将采用开放主机服务的方式向外提供API。

用户接口层是应用层的直接用户。

用户接口层在于前后端调用的适配。若你的微服务要提供服务给很多外部应用,而对每个外部应用的入参出参都不同,你不可能开发一堆一对一的应用服务,这时Facade接口就起到了很好的作用,包括DO和DTO对象的组装和转换。


由于主要负责接入各种终端,所以该层有人也叫接入层。

实际开发中,我们都会感受到该层依附于应用层存在。随前后端分离,Restful API 流行,对简单的系统来说该层越来越弱化。对于有终端接入的系统来说,该层并不简单,需要处理各种协议适配:XMPP、websocket、MQTT 等。

复杂度不高时,我们往往把该层和应用层合并部署,主要凭开发经验和理解程度来决定。


存放用户接口层与前端交互、展现数据相关的代码。


前端应用通过这层接口,向应用服务获取展现所需的数据。


该层主要用来处理用户发送的Restful请求,解析用户输入的配置文件,并将数据传递给应用层。


数据的组装、数据传输格式以及Facade接口等代码都会放在这一层目录里。


封装应用服务和对外暴露接口。

特点

  • 关心视图和对外的服务,Restful、页面渲染、websocket、XMPP 连接等
  • 如果没有多种用户端接入方式,可以和应用层合并
  • 对应到分布式系统中的网关、BFF、前台等概念
  • 只产生接入异常,例如数据校验,对应 HTTP 状态码 400、415 等
  • 一个应用可以有多个接入层
  • 接入层做和业务规则无关的 bean validation 验证
  • 准单体系统下,按照连接方式分包

该层指的是服务端用于适配端侧的部分,而非端侧本身。因为该层本就依赖应用层,无人使用接口在这里做依赖倒置,所有又被称作主动适配。

目录
相关文章
|
8月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
8月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
1314 2
Spring Boot 3.x 微服务架构实战指南
|
9月前
|
消息中间件 数据采集 NoSQL
秒级行情推送系统实战:从触发、采集到入库的端到端架构
本文设计了一套秒级实时行情推送系统,涵盖触发、采集、缓冲、入库与推送五层架构,结合动态代理IP、Kafka/Redis缓冲及WebSocket推送,实现金融数据低延迟、高并发处理,适用于股票、数字货币等实时行情场景。
1390 3
秒级行情推送系统实战:从触发、采集到入库的端到端架构
|
9月前
|
设计模式 人工智能 API
AI智能体开发实战:17种核心架构模式详解与Python代码实现
本文系统解析17种智能体架构设计模式,涵盖多智能体协作、思维树、反思优化与工具调用等核心范式,结合LangChain与LangGraph实现代码工作流,并通过真实案例验证效果,助力构建高效AI系统。
973 7
|
9月前
|
JSON 供应链 监控
1688商品详情API技术深度解析:从接口架构到数据融合实战
1688商品详情API(item_get接口)可通过商品ID获取标题、价格、库存、SKU等核心数据,适用于价格监控、供应链管理等场景。支持JSON格式返回,需企业认证。Python示例展示如何调用接口获取商品信息。
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
482 3