一、背景
之前与一位群友讨论如何在MVC应用架构下使用DDD,让DDD的一些战略战术模式配合MVC的一些架构元素来完成整个应用工程的重构升级,本篇文章将重点剖析MVC架构的一些核心特征,同时让DDD的经典分层架构与之融合,实现”上帝的归上帝,凯撒的归凯撒”。
二、MVC架构梳理
2.1 MVC架构图

2.2 MVC架构元素剖析
-
模型(Model)
从上面的架构图可以知道模型其实包含了两个职责,一个是代表业务模型在页面表示的数据容器,比如BookVO或者Book对象,另外一个则是与视图功能相关的业务功能,比如到控制器及其底层的service层都可能使用这个模型。从隐含意义上来讲,模型可能还会与特定的视图进行绑定。
-
视图(View)
在后端的视角下视图就是页面,或者弹框,所以视图会借助前端的渲染和数据绑定技术来解释模型。另外一方面视图将页面跳转路由控制的功能由后端驱动。
-
控制器(Controller)
通过上面的分析其实不难发现,控制器是整个架构的核心元素,控制器一方面控制返回模型数据一方面控制视图路由,这就造成了控制器的职责不再单一,同时也显著的耦合了视图的架构元素。
2.3 MVC架构的层次调用关系梳理
现在我们看一下MVC架构的层次调用关系,假设是一个xxx管理系统,那这里的调用链路就是 用户—>选择视图—->后端返回视图—->用户输入数据(视图)—–>控制器校验数据—>控制器调用service处理业务—>service调用数据库存储视图。从调用层次关系上来看MVC架构的一个本质特征是更面向用户接口层和应用层的架构,同时实现了前端的视图路由控制功能。
三、MVC架构整合DDD
现在我们来看一下MVC如何整合DDD,从上面的分析可以看到MVC架构是与前端严重耦合的,根据目前的架构演进趋势前后端分离基本已经是业界的事实标准了,所以在整合之前需要注意一点就是,当前的应用架构是否需要前后端分离,或者是否需要后端控制器来实现页面视图的路由。另外就需要对MVC架构的每个元素的职责进行重新划分。
3.1 C上浮与职责剥离
现在我们看一下如何对控制器进行调整,如果要让控制器去对接DDD的分层架构的话,那么很明显的就是控制器就代表着用户接口层,但是需要注意的是DDD中的用户接口层中没有涉及太多的技术细节,所以在用户接口层中不会有很多的Servlet或者Redirect。
目前的HTTP框架基本都屏蔽了底层的基本实现了。所以要让控制器上浮到分层架构的最上面,同时让C尽量也不要代表应用层。现在我们讨论一下如果控制器是否承担路由控制的场景。就目前看如果是的话那妥妥的前后端不分离了,但是依然想进行融合,所以这里需要在用户接口层中单独扩展出一个小模块来承担由之前控制器承担的责任了。
如果是要进行前后端分离,那对后端是再好不过了,对于控制器而言其职责可以减少到只进行请求和响应。题外话就是如果前后端分离的话,那就是前端来控制页面路由跳转和视图控制了。进而产生的一个效应就是M不再与具体的V进行绑定,绑定关系由前端自己控制,C此时已经不太能感知M到底要到哪个V上了。
3.2 V拆分隔离
现在我们看一下如果控制器不再参与视图的路由控制了,那MVC架构还成立吗?个人认为是成立的,同时对后端来说更轻量化,在前后端协同开发的时候后端其实已经不需要关注V的路由控制了,所以V需要的功能要从后端隔离出来让前端实现。熟悉前端的同学都知道,前端框架中的2个比较重要的功能特性就是页面视图的控制路由还有数据绑定。
以前是通过JS+JSP来进行数据绑定和渲染。但是现在看来JSP已经没有人会继续使用了,所以数据绑定和渲染都需要前端框架来实现。所以这个V在改造后的MVC架构中已经不再是必须与后端进行绑定了,同时V显得更存粹,比如渲染出的视图也许根本不需要后端参与数据返回,也就是说V已经回归到他需要站的位置了。
3.3 M冗余下沉
这里需要特别说明的是网上对MVC架构的概念职责描述的都不太一样,所以不同的博客内容其见解也不一样,有一种说法会让M看上去像是前端页面的模型。所以这里也要去伪存真一下。
现在我们看看如何改造M的部分,在DDD分层的用户接口层中的模型就是DTO,涉及到页面的也可以是VO,说白了就是数据容器,所以在写这一篇之前,先写了数据容器模式,这样的话更容易理解。那么对于M 来说其下一层是不建议透出到Service层了,所以一个必须的操作就是要将V复制到领域层,当作领域模型,也就是说需要两层模型来进行融合,让M只存在于用户接口层(也就是控制器层)。当然也不是无脑复制,改个名就完事了,如果当作领域模型的话个人建议还需要按照领域模型的构建规则进行重新梳理。所以上面的工作会产生另外一个模块,就是模型转换工具,MapStruct 或者 Spring BeanUtils都可以。
3.4 拆分后的MVC+DDD分层架构视图
现在我们来看一下拆分后的MVC架构+DDD分层应用架构的视图。上面的架构图中虚线的组件不是必须的或者是可以使用之前MVC架构下的模块,需要说明的是视图控制器是区别于是否需要前后端分离的一个重要标志,有可能是前端代码也在后端工程项目下,但是视图控制器也不存在了,此时也算前后端分离。由于SpringMVC 架构的话可能面向页面的一些操作不是很复杂,所以在项目初期的话可以使用一层转换,让领域实体与数据库实体作为一个模型,这样的话会简单一点。后期改造的话可以慢慢按标准的DDD分层架构去重构底层服务。
四、MVC架构是否过时
MVC发展的鼎盛时期,其实更关注于前后端的配合,由于前端技术的限制,不能很好的控制页面跳转,所以MVC架构就是一个前后端不分离的架构,同时就目前看MVC架构是比较少见的由后端驱动前端的架构方法。
从趋势上看MVC架构可能已经过时了,但是对于想走全栈路线或者公司没有前端资源等情况下MVC架构是后端程序员能选的一种合适的方案。当然另外一方面,对于MVC架构的实现流程和源码在面试过程中也会有所体现,如果哪天不问了,或许是真过时了。
五、实战案例
在天画的前端低代码的实现过程中就是深入实践了MVC+DDD的融合架构,项目初期使用了前后端不分离的模式,在用户接口层单独构建了视图控制器模块,其他则只是请求响应接口。后期参考Amis的web项目Demo做了前后端分离的模式,让前端代码单独用工程来构建,与后端代码完全剥离。
最近在工厂2.0项目中已经完全采用了MVC+DDD架构前后端分离的项目了,借助成熟的前端框架,相信后端程序员也可以快速构建全栈应用。想要了解项目详情的同学可以关注下面的项目:
天画前端低代码平台: https://gitee.com/sky-painting/amis4j
天画数据工厂平台: https://gitee.com/sky-painting/data-factory
原文始发于微信公众号(神帅的架构实战):DDD落地的思考–MVC+DDD理论与实践
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/241398.html