搭建柔性框架(搭建柔性框架的意义)
ccwgpt 2024-11-12 09:48 19 浏览 0 评论
本文基于我之前写的两篇文章「从架构层面看设计模式 」和「Service层需要接口吗? 」,建议阅读此文之前先阅读这两篇文章。
在「Service层需要接口吗? 」这篇文章的评论里,有朋友评论使用DDD设计的时候就需要使用接口。不过那篇文章就不是讨论DDD开发框架的,实际对应的是事务脚本开发框架。本文会在何处何时使用接口做进一步阐述。
为什么选择事务脚本开发框架呢?主要是鉴于在个人所接触的大大小小几十个项目里,使用DDD的项目寥寥无几。而在使用了DDD的项目中,有些项目就理解错了DDD;有些设计挺丰满,但落地很骨感。也就是说,从设计到代码层面时,都多多少少做了妥协。
个人认为主要原因是DDD的概念过于复杂,在进行DDD时,需要先理解很多的概念,比如:领域、子域、核心域、支撑域、通用域、实体、值对象、聚合、聚合根、领域事件等等等等。
部分概念可以参考我之前写的几篇文章:
《领域设计:Entity与VO》
《领域设计:聚合与聚合根》
《领域设计:领域事件》
这些概念不是自己理解就ok了,是需要整个团队去理解,理解了这些概念之后,才能进行设计和开发。也就是说,DDD对整个团队的要求高了几个level。
所以,DDD与国内短平快的开发模式不是很契合。DDD重设计,但大部分的企业实际是重结果,所以很多短平快的项目都使用的事务脚本的方式来进行开发。
事务脚本的方式早期开发很快,但是后期维护会比较麻烦,具体原因可以参考「从架构层面看设计模式 」,我会在下文进行一个对比。
所以我希望能搭建一个兼容事务脚本和领域设计的开发框架,能在开发效率和可维护性之间找到一个平衡。这就是我写此文的初衷。
if-else与事务脚本的关系
在「从架构层面看设计模式 」中,我将if-else与设计模式进行了对比。指出了if-else代码与使用设计模式的代码之间的6个区别:
- 边界差异
- 解耦
- 独立进化
- 对象聚集
- 依赖倒置
- 逻辑显化
实际上,事务脚本的结构和if-else的结构很类似,如下图所示:
一般我们基于事务脚本的框架分三层,Controller、Service、和Dao层。其中,
- Controller实际就对应if-else的调用层
- Service对应了if-else的逻辑层
- if-else不涉及数据持久化,所以也就没有Dao层
不过整体结构是一致的,类似的结构,也就导致了类似的问题!我们通过一个例子,来具体看一下。
举个例子
假设我们有下面这个用例:
如果,我们使用事务脚本的方式来进行开发的话,那我们的代码看起来像这样:
你能一眼就看出来代码的逻辑吗?你是不是需要完整的读完代码才能知道具体的逻辑是什么?想象一下,在后期维护的时候,你是不是每次都要看一遍这部分代码,才能回忆起来逻辑,然后才能进行修改,这个成本是不是有点太大了?
这段代码的结构如下图所示:
这段代码总体来说,有如下这些问题:
- 类职责不单一,包含了:
- 业务逻辑
- 数据库操作
- 发送短信
- Service层职责不单一:AppApplyService是业务服务,SmsService是公共服务
- 依赖有问题:业务逻辑层依赖了持久层
- 逻辑未显化:不完整读完代码无法确定逻辑
对于这些问题,我们该怎么来解决呢?
独立业务逻辑
首先,我们想到的就是「独立业务逻辑」。业务代码最核心的就是业务逻辑,我们不希望我们的业务代码淹没在一堆非业务代码中。
那我们如何独立呢?这就涉及到了我们常说的「领域建模」(注意:此处的领域建模和DDD中的领域模型是有差异的,在这里你可以把它理解为包含了业务逻辑的充血模型)。即将业务逻辑抽离到对应的对象中,针对领域模型,我们可以独立出一层,这里我们称为「业务逻辑层」。而原来的业务逻辑层我们称为「业务调用层」。如下图所示:
可以看到,独立了领域模型后,原来「业务逻辑层」对「持久层」的依赖关系也被倒置了,现在变成了「持久层」依赖于「业务逻辑层」。
为什么要依赖倒置呢?因为「业务逻辑层」使我们系统的核心,我们不希望核心逻辑依赖于非核心逻辑,这会导致核心逻辑的不稳定。
独立公共服务
接下来,我们继续进行功能拆解。将短信发送服务抽离到公共服务中。如下图所示:
这里可以看到,调整后,「业务调用层」和「业务逻辑层」都依赖了「基础层」。不过因为基础层主要提供的是基础设施,是相对比较稳定的,所以「业务逻辑层」对其依赖没有什么问题。
且「基础层」可以供多个服务使用,可以以库的形式提供出来。
隔离持久逻辑
接着,我们看一个问题。在用例中,有一个校验逻辑:需要确保「申请的应用数量<=5个」。这个逻辑我们应该放在哪里?
- 第一种方案是逻辑还在原来的Service中。不错此方案还是导致了Service中的代码逻辑不够单一,不推荐。
- 第二种方案是将逻辑独立到「业务逻辑层」,作为独立的逻辑类来处理。比如提供一个AppApplyCheckService,对应到DDD中的领域服务。然后在原Service中调用。不过这里我不推荐这么做。因为这里的校验逻辑和其后的创建逻辑构成了一个完整的业务逻辑,推荐放在一起。也就是下面说的第三个方案。
- 第三个方案,在领域模型中实现对应校验逻辑
顺便一提,上面的Service也是不需要基于接口来实现的,因为这里可以通过Spring注入,还是「业务调用层」依赖「业务逻辑层」
无论是第二种方案还是第三种方案,都会引出一个新问题:「如何查询出当前用户已经申请的应用数量?」也就是说,业务逻辑层中的对象如何调用持久层来查询数据呢?
上面说了,「业务逻辑层」不能依赖于「持久层」,所以我们这里需要做依赖倒置。引入Repository仓储接口,在持久层对其进行实现。结构图如下:
代码实现
调整后的代码如下:
这里的代码基本都是委托性代码,构建了完整的执行流程。通过对方法的友好命名,对应用例的逻辑可以在这里友好的显示出来(这里的vo.create()可能叫vo.checkAndCreate()更好一点)。
对应的核心业务逻辑代码在AppApply领域对象中:
其中的checkNum就是业务员校验逻辑:
脱离容器的测试
如此调整,所带来的一个好处,就是可以进行脱离容器的单元测试。虽然Spring提供了一些单元测试的辅助类,但是基于容器的测试由于需要启动容器,速度还是比较慢。独立了业务逻辑后,可以针对业务逻辑做单元测试。
这里需要针对Repository进行Mock,代码并不复杂。
测试在2秒内就可以完成。
柔性框架
「柔性」这个词,第一次是在DDD那本书里看到的,书中说的是「柔性设计」:「为了使项目能够随着开发工作的进行加速前进,而不会由于它自己的老化停滞不前,设计必须要让人们乐于使用,而且易于作出修改!」
就「柔性框架」而言,就是希望框架能够随着项目的推进而能够不断的演化,且能让人们乐于使用。
回到上面的框架结构:
- 在项目早期,可以使用事务脚本的方式快速进行开发。此时不需要关注「业务逻辑层」
- 项目中后期,可以引入「业务逻辑层」进行领域建模
- 对于复杂业务逻辑,可以在「业务逻辑层」进行领域驱动设计
总结
本文基于「从架构层面看设计模式 」对if-else的分析,对事务脚本代码进行重构,推导出一个适应项目全期的「柔性框架」。
相关推荐
- 详解DNFSB2毒王的各种改动以及大概的加点框架
-
首先附上改动部分,然后逐项分析第一个,毒攻掌握技能意思是力量智力差距超过15%的话差距会被强行缩小到15%,差距不到15%则无效。举例:2000力量,1650智力,2000*0.85=1700,则智力...
- 通篇干货!纵观 PolarDB-X 并行计算框架
-
作者:玄弟七锋PolarDB-X面向HTAP的混合执行器一文详细说明了PolarDB-X执行器设计的初衷,其初衷一直是致力于为PolarDB-X注入并行计算的能力,兼顾TP和AP场景,逐渐...
- 字节新推理模型逆袭DeepSeek,200B参数战胜671B,豆包史诗级加强
-
梦晨发自凹非寺量子位|公众号QbitAI字节最新深度思考模型,在数学、代码等多项推理任务中超过DeepSeek-R1了?而且参数规模更小。同样是MoE架构,字节新模型Seed-Thinkin...
- 阿里智能化研发起飞!RTP-LLM 实现 Cursor AI 1000 token/s 推理技术揭秘
-
作者|赵骁勇阿里巴巴智能引擎事业部审校|刘侃,KittyRTP-LLM是阿里巴巴大模型预测团队开发的高性能LLM推理加速引擎。它在阿里巴巴集团内广泛应用,支撑着淘宝、天猫、高德、饿...
- 多功能高校校园小程序/校园生活娱乐社交管理小程序/校园系统源码
-
校园系统通常是为学校、学生和教职工提供便捷的数字化管理工具。综合性社交大学校园小程序源码:同城校园小程序-大学校园圈子创业分享,校园趣事,同校跑腿交友综合性论坛。小程序系统基于TP6+Uni-app...
- 婚恋交友系统nuiAPP前端解决上传视频模糊的问题
-
婚恋交友系统-打造您的专属婚恋交友平台系统基于TP6+Uni-app框架开发;客户移动端采用uni-app开发,管理后台TH6开发支持微信公众号端、微信小程序端、H5端、PC端多端账号同步,可快速打包...
- 已节省数百万GPU小时!字节再砍MoE训练成本,核心代码全开源
-
COMET团队投稿量子位|公众号QbitAI字节对MoE模型训练成本再砍一刀,成本可节省40%!刚刚,豆包大模型团队在GitHub上开源了叫做COMET的MoE优化技术。COMET已应用于字节...
- 通用电气完成XA102发动机详细设计审查 将为第六代战斗机提供动力
-
2025年2月19日,美国通用电气航空航天公司(隶属于通用电气公司)宣布,已经完成了“下一代自适应推进系统”(NGAP)计划下提供的XA102自适应变循环发动机的详细设计审查阶段。XA102是通用电气...
- tpxm-19双相钢材质(双相钢f60材质)
-
TPXM-19双相钢是一种特殊的钢材,其独特的化学成分、机械性能以及广泛的应用场景使其在各行业中占有独特的地位。以下是对TPXM-19双相钢的详细介绍。**化学成分**TPXM-19双相钢的主要化学成...
- thinkphp6里怎么给layui数据表格输送数据接口
-
layui官网已经下架了,但是产品还是可以使用。今天一个朋友问我怎么给layui数据表格发送数据接口,当然他是学前端的,后端不怎么懂,自学了tp框架问我怎么调用。其实官方文档上就有相应的数据格式,js...
- 完美可用的全媒体广告精准营销服务平台PHP源码
-
今天测试了一套php开发的企业网站展示平台,还是非常不错的,下面来给大家说一下这套系统。1、系统架构这是一套基于ThinkPHP框架开发的HTML5响应式全媒体广告精准营销服务平台PHP源码。现在基于...
- 一对一源码开发,九大方面完善基础架构
-
以往的直播大多数都是一对多进行直播社交,弊端在于不能满足到每个用户的需求,会降低软件的体验感。伴随着用户需求量的增加,一对一直播源码开始出现。一个完整的一对一直播流程即主播发起直播→观看进入房间观看→...
- Int J Biol Macromol .|交联酶聚集体在分级共价有机骨架上的固定化:用于卤代醇不对称合成的高稳定酶纳米反应器
-
大家好,今天推送的文章发表在InternationalJournalofBiologicalMacromolecules上的“Immobilizationofcross-linkeden...
- 【推荐】一款开源免费的 ChatGPT 聊天管理系统,支持PC、H5等多端
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍GPTCMS是一款开源且免费(基于GPL-3.0协议开源)的ChatGPT聊天管理系统,它基于先进的GPT...
- 高性能计算(HPC)分布式训练:训练框架、混合精度、计算图优化
-
在深度学习模型愈发庞大的今天,分布式训练、高效计算和资源优化已成为AI开发者的必修课。本文将从数据并行vs模型并行、主流训练框架(如PyTorchDDP、DeepSpeed)、混合精度训练(...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 详解DNFSB2毒王的各种改动以及大概的加点框架
- 通篇干货!纵观 PolarDB-X 并行计算框架
- 字节新推理模型逆袭DeepSeek,200B参数战胜671B,豆包史诗级加强
- 阿里智能化研发起飞!RTP-LLM 实现 Cursor AI 1000 token/s 推理技术揭秘
- 多功能高校校园小程序/校园生活娱乐社交管理小程序/校园系统源码
- 婚恋交友系统nuiAPP前端解决上传视频模糊的问题
- 已节省数百万GPU小时!字节再砍MoE训练成本,核心代码全开源
- 通用电气完成XA102发动机详细设计审查 将为第六代战斗机提供动力
- tpxm-19双相钢材质(双相钢f60材质)
- thinkphp6里怎么给layui数据表格输送数据接口
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- express框架 (43)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (52)
- java框架spring (43)
- grpc框架 (55)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)