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 验证
  • 准单体系统下,按照连接方式分包

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

目录
相关文章
|
2月前
|
负载均衡 关系型数据库 应用服务中间件
高可用系列文章之二 - 传统分层架构技术方案
高可用系列文章之二 - 传统分层架构技术方案
|
2月前
|
存储 安全 网络安全
「读书笔记」《大规模分布式存储系统:原理解析与架构实战》:八
「读书笔记」《大规模分布式存储系统:原理解析与架构实战》:八
|
2月前
|
机器学习/深度学习 测试技术 Ruby
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
129 2
|
1月前
|
程序员 Python
类的设计奥秘:从代码到架构的科普全解
类的设计奥秘:从代码到架构的科普全解
13 2
|
1月前
|
运维 Linux Apache
LAMP架构调优(九)——Apache Rewrite功能实战
LAMP架构调优(九)——Apache Rewrite功能实战
13 1
|
1月前
|
消息中间件 并行计算 网络协议
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
探秘高效Linux C/C++项目架构:让进程、线程和通信方式助力你的代码飞跃
34 0
|
1月前
|
分布式计算 API 数据处理
Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
【2月更文挑战第15天】Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
60 1
|
2月前
|
Java API 调度
从Spring Cloud 开始,聊一聊微服务架构的设计与实战
随着互联网的发展,网站应用的规模也在不断的扩大,进而导致系统架构也在不断的进行变化。
369 1
从Spring Cloud 开始,聊一聊微服务架构的设计与实战
|
2月前
|
设计模式 微服务
从代码到架构,我的技术成长之路
【2月更文挑战第5天】技术是一门不断进步的艺术,我在不断的实践中,通过学习和思考,逐渐领悟到了代码、架构等方面的知识和技能。在这个过程中,我发现技术并不仅仅是一种工具,更是一种思维方式和生活态度。本文将分享我的技术成长历程和所获得的思考。
27 2
|
2月前
|
KVM 虚拟化 Android开发
DP读书:鲲鹏处理器 架构与编程(十二)鲲鹏软件实战案例Docker+KVM的部署
DP读书:鲲鹏处理器 架构与编程(十二)鲲鹏软件实战案例Docker+KVM的部署
56 1