🕸️ 第八章 Web系统的开发原则
📄 一句话概括

三层结构是【整个系统怎么竖着切】的架构风格,MVC 是【一个界面内部怎么分】的设计模式;MVC 通常就长在三层结构的表现层里,两者是包含关系,不是二选一。

📝 本节和前面几节的关系

8-1 拆出了四层【物理上的组成】,这一节换成【逻辑上的组织】:同样几块东西,代码该怎么摆。教材 8-3 的并列关键词是【MVC模型、三层结构】——这两个词经常被当成同义词,其实管的是两个不同尺度的事。

一、三层结构:管的是整个系统怎么竖着切

三层结构(也叫 n 层架构)说的是把系统按职责竖着切成三段:

它的数据流是单向逐层的:表现层 → 业务逻辑层 → 数据访问层,查的时候反向回来。 层与层之间只认接口,所以换掉数据库不需要动业务代码——这是它最大的用处。

它同时管着物理分层:这三段可以分别跑在三台机器上(Web 服务器、应用服务器、数据库服务器)。 分不分机器是部署问题,分不分代码才是架构问题,但三层结构两头都管。

二、MVC:管的是一个界面内部怎么分

MVC 是三个角色:

它的数据流是三角闭环的:用户操作 → 控制器 → 模型 → 视图 → 回到用户, 用户下一次操作再触发一轮。它是一个环,不是一条直线。

这一条就是区分两者的关键:三层结构是一条直线,MVC 是一个三角形。

三、两者的关系:不是二选一,是套装

把两个词放到同一张纸上,关系就清楚了:

常见的一种套法是这样的:表现层等于 Controller 加 View, 业务层等于 Service,数据层等于 Repository。 用一个框架同时实现两边完全不冲突—— 你不是在 MVC 和三层结构之间做单选题,而是在用 MVC 实现三层结构的最上面那一层。

一句话记住尺度:三层结构的【层】是横着切的,MVC 的【组件】是竖着切的。

四、分不清它们的后果:三种架构病

概念混着用,代码里就会长病。最常见的三种:

三条都指向同一个判断标准: 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 秒实验

  1. 随便打开一个开源 Web 项目,找它的目录结构,看能不能一眼分出三层。
  2. 回想你用过的一个后台系统:改一句提示文案,要动几个地方?
  3. 把【Model、View、Controller】三个词各用一句大白话写下来,不看笔记。

常见误区

  1. 错误:MVC 就是三层结构。——纠正:MVC 是表现层内部的设计模式,三层结构是整个系统的架构风格;范围不同,可以同时用。
  2. 错误:层分得越多越专业。——纠正:只做转发、没有任何逻辑的层是纯成本;分层要为了解决问题,不是为了好看。
  3. 错误:Controller 里写业务逻辑更省事。——纠正:省的是当下,赔的是以后——测试写不了、复用不可能、改一处动全身。
自测三问(点开对答案) 1. 三层结构和 MVC 最大的区别在哪一个维度? —— **范围与结构**:三层结构覆盖整个系统、数据流单向逐层;MVC 只在表现层内部、数据流是三角闭环。 2. 为什么说 MVC 是三层结构的一部分? —— 因为 MVC 把表现层再切成 Model、View、Controller 三份,**它解决的是界面代码怎么组织,不是整个系统怎么分层**。 3. 什么是胖控制器,为什么它是问题? —— **Controller 里堆了业务规则**。后果是改一条规则要同时动控制器、视图和测试,测试难写、逻辑无法复用。

相关笔记