第4章 Web表示层
拆分请求控制、领域模型与视图生成,比较控制器和视图模式的变化轴。
学习目标
- 能区分输入控制、领域模型调用和视图渲染三种 Web 表示层责任
- 能用 TypeScript 编写不携带业务规则的页面控制器,并返回稳定的视图模型
- 能根据页面数量、路由共享、视图变体和导航状态选择 Page Controller 或 Front Controller
为什么第4章 Web表示层值得单独学习
第4章 Web表示层的核心不是套用某个框架 API,而是决定请求如何被解释、业务模型如何被调用以及响应如何被生成。订单后台多视图通常同时包含列表、详情和导出三种表现;如果每个模板都直接访问数据库并计算业务规则,一次字段变化就会穿过路由、查询和页面,责任边界也无法测试。
↡负责解析请求、选择用例或领域行为、准备视图输入并决定响应路径的入口对象;它不应成为业务规则和数据库访问的混合容器。需要把输入协议转换为应用可以理解的意图。本页以 2024 年中文版公开目录限定第4章的范围,并依据 Martin Fowler 的作者图书页和模式目录独立重写;目录只决定要讲什么,案例、实验、判断题和答案均为本课程原创。
先建立直觉:问题、机制与代价
↡把领域或查询结果转换成用户可见结构的输出组件,例如模板、页面组件或导出格式;它不拥有订单折扣等核心业务规则。应当知道如何展示数据,而不必知道数据从哪个数据库表读取。
↡表示业务状态、行为和不变量的应用对象或查询模型,供控制器调用而不是由模板直接改写。负责领域知识,
↡把请求参数、身份和路由转换成一个用例调用,并把结果交给视图或响应格式的协调模式。负责入口协调;这样可以分别替换模板、路由和领域实现。
对第4章 Web表示层,优先比较的替代路线是:页面少且逻辑局部时采用 Page Controller,需要统一认证、路由和错误处理时采用 Front Controller;多视图共享业务数据时让控制器调用模型并生成专用 View Model。若实验只能显示页面渲染成功,不能指出请求映射、模型调用和视图生成的责任,就不能据此选择控制器模式。
目录单元到教学证据
第4章 Web表示层
第4章 Web表示层要求把“请求如何变成响应”变成可观察的架构决定:先标出输入解析、用例调用、视图选择和错误处理的所有者,再用订单后台多视图的路由测试与渲染结果验证决定。只有模板替换不会迫使业务逻辑重写,表示层边界才真正成立。
4.1 视图模式
4.1 视图模式关注如何组织展示与数据转换。模板视图适合把稳定的视图模型变成 HTML,转换视图适合把同一模型映射到不同输出;视图不应直接查询数据库或决定订单授信规则,否则页面变化会反向污染领域边界。
4.2 输入控制器模式
4.2 输入控制器模式关注请求入口的粒度与共享范围。Page Controller 让每个页面拥有清晰的输入处理,Front Controller 则把认证、路由、错误和通用上下文集中起来;选择取决于共享程度,而不是控制器类的数量。
4.3 进一步阅读
4.3 进一步阅读应把本章的 MVC 责任链连接到页面控制器、前端控制器、模板视图、转换视图和两步视图等模式。下一步阅读要回到当前应用的路由数量、视图变体和导航状态,验证模式是否解决了真实变化,而不是因为名称相近就增加抽象层。
专属代码案例:订单后台多视图
把订单后台多视图切成“请求 → 输入控制 → 模型查询 → View Model → 响应”五个观察点。第4章 Web表示层的设计草案必须写出谁拥有状态、谁作出业务决定、失败怎样传播,以及请求映射、控制器、模型、视图和导航中哪个指标最先提示当前方案不再适用。
设计记录采用五个可换行字段:单元键为 poeaa24-chapter-04-web-presentation;模式族为 web;裁决是“控制器协调输入与用例,模型拥有业务规则,视图只消费稳定的 View Model”;观测项包括请求映射、控制器、模型、视图、导航;拒绝条件是“模板直接访问数据库或在展示逻辑中修改领域状态”。
先预测:如果订单详情页改成 CSV 导出,哪些职责应该变化,哪些职责应该保持不变?先写下控制器输入、模型查询和视图转换的边界,再阅读实现;验证时应能说明同一订单数据如何被两个输出视图消费而不复制折扣规则。
type OrderSummary = {
id: string;
customerName: string;
totalCents: number;
status: "open" | "paid";
};
type OrderRequest = {
userId: string;
orderId: string;
format: "html" | "csv";
};
interface OrderQuery {
findVisibleOrder(userId: string, orderId: string): OrderSummary | undefined;
}
type OrderViewModel = {
heading: string;
customer: string;
total: string;
status: string;
};
function toOrderViewModel(order: OrderSummary): OrderViewModel {
return {
heading: `Order ${order.id}`,
customer: order.customerName,
total: `$${(order.totalCents / 100).toFixed(2)}`,
status: order.status === "paid" ? "Paid" : "Open",
};
}
class OrderPageController {
constructor(private readonly orders: OrderQuery) {}
handle(request: OrderRequest): OrderViewModel | "not-found" {
const order = this.orders.findVisibleOrder(request.userId, request.orderId);
return order ? toOrderViewModel(order) : "not-found";
}
}这段代码让控制器负责输入和查询协调,让 OrderSummary 代表模型输出,让 OrderViewModel 作为 HTML 或 CSV 视图的稳定边界。真实应用还要由路由层处理身份与错误响应;不能把折扣计算、数据库写入和模板分支继续塞进 handle。
MVC 职责分离解剖
Web 表示层的核心是把请求处理切成三个职责:Controller 解析输入并协调,Model 封装业务数据与规则,View 负责渲染。三者通过明确接口通信,各自可以独立演化;下面的图把用户操作、模型调用、视图生成和响应路径放在同一张证据图中。
选择控制器策略时,Page Controller 适合页面少且逻辑简单的场景;Front Controller 适合需要统一入口、认证、路由和错误处理的场景。无论选择哪一种,控制器都不应绕过模型直接修改持久化状态。
控制器策略决策图
先看是否存在大量共享的认证、路由和错误处理,再看页面是否拥有独立输入流程;没有共享证据时保持 Page Controller 的局部性,有共享证据时集中到 Front Controller。视图变化则通过 View Model 或转换视图隔离,而不是把条件分支复制到每个模板。
选择与拒绝矩阵
| 评审问题 | 选择表示层方案的证据 | 应拒绝当前方案的信号 |
|---|---|---|
| 责任 | 请求解析、模型调用和视图生成各有所有者 | 模板直接查询数据库或改写领域状态 |
| 变化 | View Model 隔离 HTML、CSV 和详情页变化 | 新增一个输出格式要复制全部业务规则 |
| 共享 | 认证、路由和错误处理的共享范围明确 | 为了统一而把所有页面逻辑塞进一个巨型控制器 |
| 导航 | 页面流转和失败路径可测试、可观测 | 只能从最终 HTML 猜测请求映射与错误来源 |
常见误区
可验证练习
练习
本组练习覆盖 4.1 视图模式、4.2 输入控制器模式和 4.3 进一步阅读,并要求把请求映射、控制器、模型、视图和导航映射到订单后台多视图。
问题 1:隔离输出。 同一订单需要 HTML 详情和 CSV 导出,两个模板都在计算订单总额,应该如何调整?
问题 2:选择控制器。 只有三个互不共享输入流程的页面,是否必须先建立 Front Controller?
问题 3:处理下一步阅读。 阅读两步视图或转换视图模式时,应该用什么证据判断它们是否适合当前后台?
名词解释
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 控制器
负责解析请求、选择用例或领域行为、准备视图输入并决定响应路径的入口对象。
- 视图
把领域或查询结果转换成用户可见结构的输出组件,例如模板、页面组件或导出格式。
- 模型
表示业务状态、行为和不变量的应用对象或查询模型,供控制器调用而不是由模板直接改写。
- 输入控制器
把请求参数、身份和路由转换成一个用例调用,并把结果交给视图或响应格式的协调模式。
本章小结
掌握第4章 Web表示层的标志不是记住 MVC 三个字母,而是能在订单后台多视图中解释“请求 → 输入控制 → 模型查询 → View Model → 响应”的责任链。学习者应利用请求映射、控制器、模型、视图和导航作出可证伪的选择,并在模板直接访问数据库或复制业务规则时明确拒绝当前实现。
前后导航
来源与改写范围
- Martin Fowler 作者图书页:核对全书主题、教程与模式参考结构。
- Martin Fowler 模式目录:核对模式名称、所属模式族和作者公开摘要。
- Pearson 出版社页面:交叉核对英文版出版信息与目录范围。