知识卡片

MVC的两个分离,及其重要性差异

结构图卡

内容

MVC包含三个角色:模型(不可见的领域信息与行为)、视图(模型在UI上的呈现)、控制器(接收用户输入、操作模型、让视图更新)——可以把”UI”理解成视图和控制器的结合体。理解MVC真正该关注两个分离,且这两个分离的重要程度并不相等。第一个分离——模型与表现(视图+控制器)的分离——是最基本、最重要的软件设计准则之一,原因有三:表现关心的是UI布局这类问题,模型关心的是业务规则和数据交互,两者本就是完全不同性质的关注点;分离之后,同一套模型代码可以配上多种表现(富客户端、Web浏览器、远程API、命令行……甚至同一应用不同页面各有不同UI),而不用重复实现业务逻辑;不可见对象天生比可见对象更容易测试,分离出来的模型逻辑可以脱离笨拙的GUI测试工具直接验证。这个分离的关键在于依赖方向必须是单向的:表现依赖模型,模型绝不能依赖表现——写模型代码时完全不该知道当前是哪种表现在用它,这样表现层才能自由演化、增加新表现也不会牵连模型。第二个分离——视图与控制器的分离——重要程度低得多,作者的态度是”仅当确实有用时才做”:多数系统里一个视图往往只配一个控制器,几乎每个版本的Smalltalk都没有真正分离过视图和控制器;这个分离在Web前端场景下才重新变得有用(也是Web设计中大量模式的基础),典型理由是想用同一个视图搭配两种不同的控制器策略来实现”可编辑”和”只读”两种模式。作者特别提醒一个常见的误引用:很多人把”控制器”理解成”位于模型和视图之间”的中介层(比如应用控制器),但应用控制器和MVC里的控制器其实是完全不同的两个概念,不该混为一谈。

结构图

flowchart TB
  A["MVC三角色"]
  A --> M["模型:领域信息与行为(不可见)"]
  A --> V["视图:模型的UI呈现"]
  A --> C["控制器:接收输入/操作模型/驱动视图更新"]
  P["分离一:模型↔表现(视图+控制器)"] -->|"最重要<br/>单向依赖:表现依赖模型"| A
  Q["分离二:视图↔控制器"] -->|"次要,仅在需要时做<br/>如支持可编辑/只读两种控制器策略"| A

参考来源

- 位置:《企业应用架构模式》第二部分"模式"之"第14章 Web表现模式"之"14.1 模型-视图-控制器"(源文件:_epub-src/OEBPS/Text/000155.html、000156.html) - 结论依据:原文说明"考虑MVC的时候,我关注两个主要的分离:从模型中分离表现和从视图中分离控制器……这个分离的关键点是依赖的方向:表现依赖模型,但是模型不依赖表现……第二个分离,视图和控制器的分离,就不那么重要了……大部分系统的每个视图只有一个控制器,所以这种分离常常没有做到",直接支撑本卡结构图。 - 原始内容:不管应用控制器有多少优点,它与MVC中的控制器完全不同。