三层结构是【整个系统怎么竖着切】的架构风格,MVC 是【一个界面内部怎么分】的设计模式;MVC 通常就长在三层结构的表现层里,两者是包含关系,不是二选一。
8-1 拆出了四层【物理上的组成】,这一节换成【逻辑上的组织】:同样几块东西,代码该怎么摆。教材 8-3 的并列关键词是【MVC模型、三层结构】——这两个词经常被当成同义词,其实管的是两个不同尺度的事。
一、三层结构:管的是整个系统怎么竖着切
三层结构(也叫 n 层架构)说的是把系统按职责竖着切成三段:
- 表现层——接收用户输入、把结果画出来。也叫 UI 层。
- 业务逻辑层——规则、校验、事务。真正决定【能不能】的那一层。
- 数据访问层——只管读写数据库,别的不管。也叫持久层。
它的数据流是单向逐层的:表现层 → 业务逻辑层 → 数据访问层,查的时候反向回来。 层与层之间只认接口,所以换掉数据库不需要动业务代码——这是它最大的用处。
它同时管着物理分层:这三段可以分别跑在三台机器上(Web 服务器、应用服务器、数据库服务器)。 分不分机器是部署问题,分不分代码才是架构问题,但三层结构两头都管。
二、MVC:管的是一个界面内部怎么分
MVC 是三个角色:
- Model(模型)——数据与业务规则。它是唯一知道真相的那一方。
- View(视图)——只负责显示,拿到什么画什么,不做判断。
- Controller(控制器)——接住用户动作,去问 Model,再挑一个 View。
它的数据流是三角闭环的:用户操作 → 控制器 → 模型 → 视图 → 回到用户, 用户下一次操作再触发一轮。它是一个环,不是一条直线。
这一条就是区分两者的关键:三层结构是一条直线,MVC 是一个三角形。
三、两者的关系:不是二选一,是套装
把两个词放到同一张纸上,关系就清楚了:
- 三层结构是架构风格,范围覆盖整个系统,从界面一路到数据库。
- MVC 是设计模式,范围只在表现层内部。
- 所以:MVC 是三层结构里【表现层】的一种具体做法。
常见的一种套法是这样的:表现层等于 Controller 加 View, 业务层等于 Service,数据层等于 Repository。 用一个框架同时实现两边完全不冲突—— 你不是在 MVC 和三层结构之间做单选题,而是在用 MVC 实现三层结构的最上面那一层。
一句话记住尺度:三层结构的【层】是横着切的,MVC 的【组件】是竖着切的。
四、分不清它们的后果:三种架构病
概念混着用,代码里就会长病。最常见的三种:
- 胖控制器——业务规则写进了 Controller。结果是改一条规则要同时动控制器、视图和测试,谁都不敢动。
- 贫血模型——Model 只剩下取值和赋值,真正的逻辑全堆到 Service 里。结果是 Service 变成臃肿的上帝类。
- 传递层——某一层只是把调用转发给下一层,自己不做任何判断。这一层是白加的。
三条都指向同一个判断标准: Controller 应当是【轻量协调者】,不是业务仓库;业务规则应当留在该负责的那一层里。
五、动手 Demo:算一下放错位置的代价
用同一个需求,看两种放法各要牵动几个文件——这就是【胖控制器】的代价:
# 需求:给订单加一条折扣规则
n1 = ["Model(规则本体)", "测试"]
n2 = ["Controller(规则本体)", "View(要重取数据)", "测试"]
print(" 放在 Model 里,要动 %d 个文件" % len(n1))
print(" 塞进 Controller,要动 %d 个文件" % len(n2))
print(" 差 %.1f 倍——这就是胖控制器的代价" % (len(n2) / len(n1)))
实跑输出:
--------------------------------------------------------------------
MVC 和三层结构,到底谁套着谁
--------------------------------------------------------------------
这两个词经常被当成同义词,其实管的是两个不同尺度的东西。
先看三层结构——它说的是整个系统怎么竖着切:
层 职责
----------------------------------------------------
表现层 接收用户输入、把结果画出来
业务逻辑层 规则、校验、事务——真正决定【能不能】
数据访问层 只管读写数据库,别的不管
----------------------------------------------------
它的数据流是单向的:表现层 → 业务逻辑层 → 数据访问层,查的时候反向回来。
层与层之间只认接口,所以换掉数据库不用动业务代码。
再看 MVC——它说的是一个界面内部的代码怎么分:
角色 职责
-------------------------------------------------------
Model 数据与业务规则,是唯一知道真相的那方
View 只负责显示,拿到什么画什么
Controller 接住用户动作,去问 Model,再挑一个 View
-------------------------------------------------------
它的数据流是三角形的:用户 → 控制器 → 模型 → 视图 → 用户。
所以两者的关系一句话说清:
维度 三层结构 MVC
-------------------------------------------
本质 架构风格 设计模式
关注点 系统级分层 界面内部组织
范围 从界面到数据库 只在表现层内
结构 线性逐层 三角闭环
-------------------------------------------
落到实际代码上,最常见的一种套法是这样的:
表现层 ≈ Controller + View,业务层 ≈ Service,数据层 ≈ Repository。
也就是说,MVC 是三层结构里【表现层】的一种具体做法。
分不清它们的后果,就是三种常见的【架构病】:
毛病 症状
----------------------------------------------------
胖控制器 业务规则写进 Controller,越改越不敢动
贫血模型 Model 只剩取值赋值,逻辑全堆到 Service
传递层 Service 只是转发,没有任何自己的逻辑
----------------------------------------------------
一条判断标准:Controller 该是【轻量协调者】,不是业务仓库。
改动范围会随着项目变大而放大。 这里只是三个文件,真实项目里一层套一层,牵动十几个文件是常事。 架构的价值不在于写得漂亮,而在于一年后还敢改。
30 秒实验
- 随便打开一个开源 Web 项目,找它的目录结构,看能不能一眼分出三层。
- 回想你用过的一个后台系统:改一句提示文案,要动几个地方?
- 把【Model、View、Controller】三个词各用一句大白话写下来,不看笔记。
常见误区
- 错误:MVC 就是三层结构。——纠正:MVC 是表现层内部的设计模式,三层结构是整个系统的架构风格;范围不同,可以同时用。
- 错误:层分得越多越专业。——纠正:只做转发、没有任何逻辑的层是纯成本;分层要为了解决问题,不是为了好看。
- 错误:Controller 里写业务逻辑更省事。——纠正:省的是当下,赔的是以后——测试写不了、复用不可能、改一处动全身。
自测三问(点开对答案)
1. 三层结构和 MVC 最大的区别在哪一个维度? —— **范围与结构**:三层结构覆盖整个系统、数据流单向逐层;MVC 只在表现层内部、数据流是三角闭环。 2. 为什么说 MVC 是三层结构的一部分? —— 因为 MVC 把表现层再切成 Model、View、Controller 三份,**它解决的是界面代码怎么组织,不是整个系统怎么分层**。 3. 什么是胖控制器,为什么它是问题? —— **Controller 里堆了业务规则**。后果是改一条规则要同时动控制器、视图和测试,测试难写、逻辑无法复用。- ☐ 下一节(8-4 开发框架:React、Vue.js、Angular)
相关笔记
- Web应用后端的构成元素 —— 上一节讲物理四层,这一节讲逻辑分层
- 将客户端与服务器分离 —— 分层思想的第一次出现
- MVC、MVVM-划分GUI应用的功能 —— 同一组概念的另一种讲法
- C++类 —— 对象怎么组织,是分层的前提
- 🕸️ Web技术原理 · 索引