从一层到多层架构的学习笔记
为什么要分层
- 支持技术复杂性与业务复杂性分离
- 分层需要明确每层的职责,单一职责,做到关注点分离
- 需要通过分层来隔离不同的关注点,以此应对不同需求的变化
- 在项目中约定每层的规范,有利于代码的规范,更好的阅读性
- 在代码实现中,可以减少耦合,避免一些重复,避免一些臃肿
学习三层的过程
一层架构,二层架构
1.最开始写代码,直接在Controller
上写业务逻辑,以及数据交互的代码,这样写在控制器上存在大量的重复代码,十分的凌乱,阅读性非常差。
2.前人走后,后来的人接手,一脸蒙逼,眼花缭乱,一个方法,几百行代码是基本操作,里面包含了大量的业务逻辑,访问DB,有的还用了视图,存储过程,不知道你们遇到过没有,我是遇到过的。
3.只要经历过维护这种代码的,基本上会发现。有大量的重复,可以抽离出来,许多代码都可以共用,于是抽象出公共的方法,大量的业务逻辑代码在Controller上不好维护, 把业务逻辑也抽离出来,单独一层,把所有的业务逻辑都写到业务逻辑层,出现了二层架构。
三层架构
1.在二层架构中,会发现,业务逻辑层中还是有大量的数据访问的代码,根据单一职责,业务逻辑层应该更多关注的是,业务逻辑,而且,数据访问的代码也存在许多重复的现象,于是抽出业务逻辑层中的数据访问代码到数据访问层 出现了三层架构。
2.一层到三层的出现,在我的认知里,就是为了减少重复,避免臃肿,分离后,每一层都有自己的职责,基于约定,代码的阅读性更好
3.任何软件工程遇到的问题都可以通过增加一个第二步实现需求来解决
这句话是真的经典!
领域驱动设计的经典分层架构
领域驱动设计的经典四层架构:基础设施层
,领域层
,应用层
,用户界面/展现层
用户界面/展现层
:负责向用户展现信息以及解释用户命令,是请求的入口,获取和展示用户需要的数据,传递命令给应用层
应用层
:很薄的一层,用来协调应用的活动,它不包含业务逻辑,包含控制扭转逻辑,对外为展现层提供各种应用功能(包括查询或命令),对内调用领域层(领域对象或领域服务)完成各种业务逻辑
基础设施层
:本层作为其他层的支撑库存在。它提供了层间的通信,实现对业务对象的持久化,可以通过架构和框架来支持其他层的技术需求
领域层
:包含业务逻辑,是业务软件的核心所在。在这里保留业务对象的状态,业务逻辑都应该包含在领域层中
光看这些概念80%的人都会懵圈,DDD中有许多的术语都需要去了解,现在我们来看一些术语对应在那一层,代码上怎么体现
术语对应在那一层
由于仓储中包含持久化,领域层不应该依赖于技术细节,通过依赖注入,所以仓储实现部分定义在基础设施层,仓储的定义在领域层
应用层
:应用服务
,工作单元
领域层
:实体
,值对象
,聚合
,聚合根
,领域服务
,领域事件
,仓储定义部分
,Process manager(Saga)事件流程管理器
基础设施层
:仓储实现部分
代码上怎么体现
单体
1.我比较喜欢使用,解决方案文件夹给分层架构命名,在解决方案文件夹下面,按照规则建立对应的类库
2.API接口的命名和应用服务的命名,非常重要,命名应该按照业务的用例来命名,因为单体项目的数据库,和代码可能都是写在一起的,一个业务命令可能涉及到多个上下文的交互
3.所有上下文的领域模型都在一起,必须通过约定的规则来命名,才能更好的分辨,表达业务语义,也便于以后的拆分
4.多个限界上下文的交互的通讯方式是本地访问,需要在应用层组装返回数据,或者在应用层使用工作单元,使用本地事务来确保成功,失败
5.个人感觉DDD经典架构和三层架构的区别不是很大,只是DDD经典架构中有一些新的术语,把业务逻辑层,拆分为,应用层和领域层,按照OO来说,代码模型中应该包含业务逻辑,所以把业务逻辑层的业务都转移到了代码模型里面,DDD要求我们业务逻辑都应该包含在领域模型中,所以有些业务逻辑根据职责的划分,放在模型里面不合适时:就出现了领域服务
6.领域事件和Saga不是必须的,引入需要慎重考虑,一但引入,实现难度,维度难道系数,成几何倍数增长
微服务
1.OrderBoundedContext
:表示订单的界限上下文,一般来说每一个界限上下文就是一个微服务,要看服务划分的力度,在界限上下文中,可以根据业务选择不同的技术架构,可以是微服务架构,也可以是三层架构
领域层
:
应用层
:
基础设施层
:
用户界面/展现层
:
分层总结
一:项目结构分层是有代价的,分层必定会带来一定的工作量
二:分层的意义就是提升代码的可维护性,阅读性,重用性,明确职责,避免大量的重复
三:最好的架构分层,必须是基于约定的,只有遵守约定,才是好的架构
四:架构的选择,需要根据业务和团队的实际情况来选择,没有最好的架构,也没有最差的架构,只有最适合的架构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端