MVC模式和DDD模式对比,谁才是银弹?
目录
从DDD的角度看MVC架构的问题
第一层:初出茅庐
第二层:草船借箭(战术设计)
第三层:运筹帷幄(战略设计)
DDD的不足
总结
MVC模式和DDD模式对比,谁才是银弹?
DDD这几年越来越火,资料也很多,大部分的资料都偏向于理论介绍,有给出的代码与传统MVC的三层架构差异较大,再加上大量的新概念很容易让初学者望而却步。本文从MVC架构角度来讲解如何演进到DDD架构。
关注我 code 杂坛,了解更多......
从DDD的角度看MVC架构的问题
代码角度:
瘦实体模型:只起到数据类的作用,业务逻辑散落到service,可维护性越来越差;
面向数据库表编程,而非模型编程;
实体类之间的关系是复杂的网状结构,成为大泥球,牵一发而动全身,导致不敢轻易改代码;
service类承接的所有的业务逻辑,越来越臃肿,很容易出现几千行的service类;
对外接口直接暴露实体模型,导致不必要开放内部逻辑对外暴露,就算有DTO类一般也是实体类的直接copy;
外部依赖层直接从service层调用,字段转换、异常处理大量充斥在service方法中。
项目管理角度:
交付效率:越来越低;
稳定性差:不好测试,代码改动的影响范围不好预估;
理解成本高:新成员介入成本高,长期会导致模块只有一个人最熟悉,离职成本很大。
关注我 code 杂坛,了解更多......
第一层:初出茅庐
以上的问题越来越严重,很多人开始把眼光转向DDD,于是埋头啃了几本大部头的书,对以下概念有了基本的了解:
统一语言
限界上下文
领域、子域、支撑域
聚合、实体、值对象
分层:用户接口层、应用层、领域层、基础层
于是把MVC架构进行了改造,演进成DDD的分层架构。
DDD分层架构:
MVC架构到DDD分层架构的映射:
至此,算了基本入门了DDD架构,扩展性也得到了一定的提升。不过随着业务的发展,不断冒出新的问题:
一段业务逻辑代码,到底应该放到应用层还是领域层?
领域服务当成原来的MVC中的service层,随着业务不断发展,类也在不断膨胀,好像还是老样子啊?
聚合包含多个实体类,这个接口用不到这么多实体,为了性能还是直接写个SQL返回必要的操作吧,不过这样貌似又回到了MVC模式
既然实体类可以包含业务逻辑、领域服务也可以放业务逻辑,那到底放哪里?
资料上说领域层不能有外部依赖,要做到100%单测覆盖,可是我的领域服务中需要用到外部接口、中央缓存等等,那这不就有了外部依赖了吗?
关注我 code 杂坛,了解更多......
第二层:草船借箭(战术设计)
带着问题不断学习他人经验,并不断的尝试,逐渐get到以下技能:
1、领域层
领域(domain)是个模块,包含以下组成部分,传统的service按功能可能拆分到任何一个地方,各司其职。
1个聚合
1到多个实体
若干值对象
多个DomainService
1个Factory:新建聚合
1个Repository:聚合仓储服务
聚合根(AggregateRoot):
聚合本身也是一个实体,聚合可以包含其他实体,其他实体不能脱离聚合而单独提供服务,比如一篇文章下的评论,评论必须从属于文章,没有文章也就没有评论。仓库层(repository)也必须是以聚合为核心提供服务的。
实体可以理解为一张数据库表,必须有主键。
值对象没有主键,依附于实体而存在,比如用户实体下住址对象,一般在数据库中已json字符串的形式存在;最常见的值对象是枚举。
仓库服务(repository):
资源库是聚合的仓储机制,外部世界通过资源库,而且只能通过资源库来完成对聚合的访问。资源库以聚合的整体管理对象。因此,一个聚合只能有一个资源库对象,那就是以聚合根命名的资源库。除此之外的其他对象,都不应该提供资源库对象。仓储服务的实现一般有Spring Data JPA、Mybatis两种方式。
如果是用Spring Data JPA实现,直接使用JPA注解@OneToOne、@OneToMany,配合fetch配置,即可一个方法查询出所有的关联实体。
如果是用Mybatis实现,那么repository需要加入多个mapper的引用,再手动做拼装。
这里有一个经典的Hibernate笛卡尔积问题,答案是在聚合根中,一般不会加在大量的关联实体对象。如果确实需要查询关联对象而关联对象又比较多怎么办呢?在DDD中有一个CQRS(Command-Query Responsibility Segregation)模式,是一种读写分离模式,在此场景中需要将查询操作放到查询命令中分页查询。
当然CQRS也是一个很复杂模式,不应照搬他人方案,而是根据自己的业务场景选择适合自己的方案,以下列举了CQRS的几种应用模式:
单服务/跨服务 共享模型/不同模型 共享存储/不同存储 适用场景
单服务 共享模型 共享存储 不算CQRS,但对于很多中小型项目已经足够
单服务 不同模型 共享存储 适用于查询比较复杂的场景
单服务 不同模型 不同存储 适用于查询比较复杂且对查询效率要求较高的场景
跨服务 不同模型 不同存储 主要用于微服务中需要对多个服务进行聚合查询的场景
工厂服务(factory):
作用是创建聚合,只传入必要的参数,工厂服务内部隐藏复杂的创建逻辑。简单的聚合可以直接通过new、静态方法等创建,不是必须由factory创建。
领域服务:
单个实体对象能处理的逻辑放到实体里,多个实体或有交互的场景放到领域服务里。
领域服务可不可以调用仓储层或外部接口?可以,但不能直接和领域服务代码放一起,领域服务模块存放API,实现放基础层(infrastructure)。
领域服务对象不建议直接以聚合名+DomainService命名,而要以操作命令关联,比如用户保存服务命名为:UserSaveService, 审核服务:UserAuditSerivce。
2、应用层
应用层通过应用服务接口来暴露系统的全部功能。在应用服务的实现中,它负责编排和转发,它将要实现的功能委托给一个或多个领域对象来实现,它本身只负责处理业务用例的执行顺序以及结果的拼装。通过这样一种方式,它隐藏了领域层的复杂性及其内部实现机制。
比如下订单服务的方法:
public void submitOrder(Long orderId) {
Order order = OrderFetchService.fetchById(orderId); //获取订单对象
OrderCheckSerivce.check(order); //验证订单是否有效
OrderSubmitSerivce.submit(order); //提交订单
ShoppingCartClearService.clear(order); //移除购物车中已购商品
NotifySerivce.emailNotify(order.getUser()); //发送邮件通知买家
}
对于复杂的业务来说,应用层也有几种模式:
编排服务:最典型比如Drools;
Command、Query命令模式;
业务按Rhase、Step逐层拆分模式;
3、Maven模块划分
基础层是比较简单一层,不过这里还有个比较疑惑的问题:按照DDD的四层架构图去划分Maven模块,基础层是最上的一层,但是基础层也要包含基础组件供其他层使用,这时基础层应该是放到最下层,直接按照这样构建Maven模块会造成循环依赖。
相比来说,另一个架构图更准确一些,不过依然没有直观体现Maven模块如何划分。
我的最佳实践是将基础层拆分两部分,一部分是基础的组件+仓储API,一部分是实现,maven模块划分图如下所示:
第三层:运筹帷幄(战略设计)
经过以上的两层的磨炼,恭喜你把DDD战术都学习完了,应付日常的代码开发也够了,不过作为架构师来说,探索的道路还不能止步于此,接下来会DDD战略部分。战略部分关注点有3个:
————————————————
版权声明:本文为CSDN博主「魏小言」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34417408/article/details/124382079
相关推荐
无刷直流电机模糊神经网络PID-模糊PID-传统PID三种控制对比Simulink仿真
内容概要:本文系统研究了无刷直流电机(BLDCM)在Simulink环境下的三种控制策略:传统PID控制、模糊PID控制以及模糊神经网络PID控制。研究基于三相桥式星型全控电路结构,构建了转速电流双闭环控制系统,并通过Matlab/Simulink搭建仿真模型,全面对比分析了三种算法在动态响应速度、稳态精度、抗干扰能力及系统鲁棒性等方面的性能差异。文章深入阐述了各控制方法的设计原理与实现机制,重点突出了模糊逻辑与神经网络在自适应调节PID参数方面的优势,验证了智能控制算法在提升电机控制品质上的显著效果。同时,文档提供了详实的仿真资源、参考文献和技术说明,有助于读者复现实验并深化对先进控制策略的理解与应用。 适合人群:具备自动控制理论基础和MATLAB/Simulink仿真能力的电气工程、自动化及相关专业的研究生、科研人员及工程技术人员,特别适用于从事电机驱动系统设计、智能控制算法开发等领域的专业人士。 使用场景及目标:①用于教学与科研中对比分析传统PID、模糊PID与模糊神经网络PID在无刷直流电机调速系统中的控制性能差异;②为高性能电机控制器的设计与优化提供仿真验证平台,支持参数整定与控制策略选型;③辅助完成毕业设计、科研项目或工业应用中的控制算法评估与改进。 阅读建议:建议读者结合所提供的Simulink模型与参考文献,逐步复现仿真过程,重点关注不同控制器的参数整定方法、响应曲线特征及其在负载扰动下的表现。可进一步拓展研究方向,如引入无位置传感器控制、滑模观测器或模型预测控制等先进控制技术,以深化对现代电机智能控制体系的理解与创新能力。
分省份-城投债信用利差跟踪(私募债)20260206.xlsx
分省份-城投债信用利差跟踪(私募债)20260206.xlsx
高校技术转移办公室人员如何高效管理技术成果全生命周期?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。
傲梅备份软件-windows系统
文件增量、全量定时备份
科技中介服务机构如何提升技术供需对接的智能化水平?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。



