很多开发者写了几年代码,依然搞不懂一个核心问题:
为什么前端用 MVVM,后端用 MVC?两者本质区别是什么?Spring 里的 Service 到底存在的意义是什么?所谓 DDD 极致面向对象,到底是换皮还是真架构升级?
本文结合前后端实战架构、源码分层思想、Spring 工程实践、DDD 落地真相,一次性彻底讲透这套架构体系,终结所有混淆认知。
一、先分清:前端 MVVM 与 传统后端 MVC 的本质差异
1. 核心底层逻辑:同源思想,不同场景
不管是 MVC 还是 MVVM,核心思想都是 声明式编程、分层解耦、框架自动绑定,和 Spring 「XML配置 / 注解配置」思想完全一致:
-
开发者只声明关系、不写繁琐胶水代码
-
框架负责解析、绑定、自动联动
-
彻底解耦业务与底层实现
2. Vue3 工程化:最标准的 MVVM 落地
很多人疑惑:Vue 的 template 和 script setup 在同一个 .vue 文件,算不算违背分层?
答案:物理合并,逻辑严格分层,完全标准 MVVM。
Vue3 标准目录 & MVVM 精准对应:
-
View 视图层 :
views/、components/中所有\<template\>代码,只负责展示UI、接收用户操作,无业务、无请求 -
ViewModel 中间层 :
script setup、composables/、Pinia,负责状态管理、事件处理、业务调度、连接视图与数据层 -
Model 数据层 :
api/、utils/,负责网络请求、数据处理、数据源提供,完全不碰UI
核心数据流:View 触发操作 → ViewModel 处理逻辑 → Model 获取数据 → 响应式自动更新 View
3. 安卓原生 MVVM(物理完全拆分)
安卓传统 MVVM 与 Vue 最大区别:三层物理文件完全隔离
-
View:XML 布局文件(纯UI)
-
ViewModel:独立 Java/Kotlin 类(纯逻辑状态)
-
Model:Repository 数据层(数据与接口)
Vue 是为了工程维护便利,将 View 和 ViewModel 合并为 SFC 单文件,但逻辑分层不变。
二、后端 Spring 架构:为什么只用 MVC,不用 MVVM?
1. 后端无UI交互,不需要 MVVM
MVVM 诞生的核心目的:解决交互式UI的频繁更新、双向绑定问题。
而后端是请求-响应模型 ,无常驻视图、无实时UI刷新,天然不需要 ViewModel 层,因此后端永远主力架构为 MVC。
2. 后端 MVC 的真实分层(纠正最大误区)
原生 MVC 只有三层:Model、View、Controller。
Spring 工程的 Service、Mapper、Entity 并不是新增分层,而是 Model 层的内部分层细化:
-
Controller(C):接收请求、参数校验、调度流程、返回JSON(后端的View就是响应JSON)
-
Model(M):包含 Entity(数据实体)、Service(业务逻辑)、Mapper(数据读写)
3. 传统三层架构的致命问题:贫血模型、过程式编程
我们日常写的 Controller → Service → Mapper 架构,是工程妥协的过程式架构:
-
Entity 只有字段、get/set,是纯数据壳子(贫血模型)
-
所有业务规则、状态判断、流程逻辑全部堆在 Service
-
彻底丢失面向对象思想:数据和行为分离
这也是为什么很多后端代码越写越乱、业务散落、无法维护的核心根源。
三、极致OOP 追求:重构后端 MVC,回归对象本质
1. 极致面向对象的核心标准
真正的 OOP 只有一个核心:高内聚,数据与行为归属同一个对象
对象应该自己拥有数据、自己执行业务规则、自己管理状态,而不是被外部 Service 指挥。
2. 传统 MVC 的痛点:Service 抢走了 Model 的活
常规开发中,Service 大包大揽:查库、判断规则、状态流转、流程编排,直接导致:
-
Model 彻底沦为哑巴数据类
-
代码变成过程式脚本,毫无面向对象可言
-
相同业务规则散落多处,难以统一维护
3. 极致OOP 改良方案:拆解 Service,回归充血模型
想要极致 OOP,核心改造只有一步:把 Service 的职责拆分,将业务行为还给 Model
-
充血 Domain Model:封装自身数据、业务规则、状态流转(核心OOP)
-
Repository 仓储层:接管 Mapper,只做数据存取、对象组装,无业务逻辑
-
DomainService 领域服务:仅处理跨实体、跨领域的流程编排,不写细粒度业务规则
-
应用层 Controller:极致轻薄,只做请求接收与流程调度
四、DDD 领域事件:解决 Model 不能注入DAO的终极难题
1. 核心矛盾
极致OOP要求 Model 高内聚,但 Spring 中实体类不是Bean,无法注入 Mapper/DAO,不能直接操作数据库。
如果强行静态注入,会耦合框架、臃肿难维护。
2. 高阶解法:领域事件解耦(纯净DDD方案)
核心思想:领域Model只负责业务和状态,不负责持久化、不碰数据库
-
Domain Model:执行业务规则、修改状态、发布领域事件
-
事件监听器(基础设施层):监听事件,统一完成存库、发MQ、记日志、消息推送
-
所有数据库操作、框架副作用,全部剥离出领域层
优势:领域层彻底纯净、零框架依赖、零DB依赖,完全符合极致OOP。
3. 数据查询问题的标准答案
很多人疑惑:Model 不能查数据怎么办?
DDD铁律:领域对象永不主动查库
所有数据查询、聚合加载,统一由 Repository 仓储层提前查好、组装完整,喂给领域对象,Model 只负责执行业务。
五、彻底厘清:DomainService、Repository 与传统 Service 的区别
很多人误以为 DDD 只是换皮 MVC,只是拆了 Service,实则核心权责完全不同:
1. 传统 MVC Service
-
大包大揽:查库、业务判断、状态流转、流程编排、持久化全部包揽
-
抢走 Model 业务职责,导致实体贫血
-
过程式编程,破坏面向对象
2. Repository 仓储层
-
只负责数据存取、领域对象组装、屏蔽数据库细节
-
绝不写任何业务规则
-
依赖倒置:领域层只依赖抽象接口,不依赖具体实现
3. DomainService 领域服务
-
只处理跨实体、跨领域的复杂业务编排
-
不写细粒度业务规则,具体规则全部下沉到 Domain Model
-
无状态,仅调度,不抢对象本职工作
六、内部类在极致OOP/DDD中的核心价值
在轻量化 DDD 落地中,内部类是解决「类太多、分层太碎、边界混乱」的最优解:
-
强归属高内聚:子实体、值对象、状态枚举、工厂方法收拢在主领域实体内部
-
天然聚合边界:实现 DDD 聚合根隔离,禁止外部独立篡改子实体
-
减少碎类泛滥:不用新建大量微型独立文件,架构更简洁
-
权限隔离:私有内部类可实现内部规则隐藏,从语法层面锁死分层边界
七、真实工业级DDD项目(非Demo)落地特征
区分Demo和生产级DDD的核心:不是包结构,是职责边界和分层规范
生产级 DDD 项目统一特征:
-
严格单向依赖:外层依赖内层,无跨层乱调用、无反向依赖
-
领域层纯净:无Spring、无MyBatis、无任何框架/DB依赖
-
业务内聚:对象自身规则全部在 Domain Model,无散落业务
-
技术细节收敛:所有DB、中间件、事件实现全部在基础设施层
优质开源生产级参考:阿里COLA、微软eShopOnContainers、ABP Framework
八、最终总结:三种架构的终极定位
-
前端 Vue3 MVVM:适配交互式UI,视图与逻辑解耦,双向响应式绑定,工程化落地最优解
-
传统后端 MVC:工业化分层、适合团队协作,但贫血模型、过程式编程,丢失OOP思想
-
DDD极致OOP架构:重构MVC职责,业务回归领域对象,分层清晰、高内聚、低耦合,复杂业务系统最优架构
一句话收尾:
MVC/MVVM 是架构模式 ,DDD 是业务建模思想 ;传统分层是工程妥协,充血领域模型才是面向对象的终极本质。
(注:文档部分内容可能由 AI 生成)