MVC是一个巨大误会

Posted 优才网

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MVC是一个巨大误会相关的知识,希望对你有一定的参考价值。

我是web工程师,从刚开始学MVC就深感困惑:

怎么每个地方说的MVC都不太一样?

有些文章讲的MVC,跟我正在用的MVC,怎么像完全不同的东西?

Model、Controller、View三者到底如何互动?真是一个定义不明、含糊不清的名词。

这让我研究了很久。最后,发觉它是一个严重的误会。

这个误会导致了学习和沟通上的代价,请听我娓娓道来。

哪些是MVC?

web领域,不论前端(client-side)、后端(server-side)、不论什么程式语言,几乎所有framework都自称、或被认为是「MVC」。

有哪些呢?

前端:Backbone.js、AngularJS、Ember.js…

后端:Ruby on Rails、CodeIgniter、Laravel、Django…

真的是这样吗?它们全都是MVC吗?

MVC是什么?

该怎么定义MVC呢?

我们先来看看维基百科怎么说:

MVC模式(Model-View-Controller)是软体工程中的一种软体架构模式,把软体系统分为三个基本部分:模型(Model)、检视(View)和控制器(Controller)。

嗯,跟大家说的一样。我们继续往下看:

模型(Model) 用于封装与应用程式的业务逻辑相关的资料以及对资料的处理方法。「 Model 」有对资料直接存取的权力,例如对资料库的存取。「Model」不依赖「View」和「Controller」,也就是说, Model 不关心它会被如何显示或是如何被操作。但是 Model 中资料的变化一般会通过一种重新整理机制被公布。为了实作这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而,View 可以了解在资料 Model 上发生的改变。(比较:观察者模式(软体设计模式))

看起来有些陌生,整段描述跟你的web开发经验完全不同,对吗?

最大的疑问来自这句:

那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而,View 可以了解在资料 Model 上发生的改变。(比较:观察者模式(软体设计模式))

后面直接叫你去看观察者模式(observer pattern)。

问题来了:你有在view跟model之间实作observer pattern吗?

也就是说,你的Model在资料改变之后,能主动通知View吗?

没有的话,就根本不符合MVC的定义。

全都不是MVC?

我们现在发现MVC有observer pattern这个必要条件了。

事情严重了起来。

client-side framework或许能够符合这个条件。

以Backbone.js官网范例来说,我们可以这样在Model上注册:


它的确实作了observer pattern。

但server-side framework呢?

你的Model如何能在发生改变之后去「主动通知」View?

你平常开发web哪有用到server push的技术?

所有server-side framework,从Ruby的Rails;php的CodeIgniter、Laravel;到Python的Django,他们全都不是MVC。

它们实作的,是昇阳电脑在1998年提出的「Model 2」。

什么是Model 2?

Model 2名气不大,在维基百科连中文条目都没有。我们看看英文条目怎么讲:

Model 2 is a complex design pattern used in the design of Java Web applications which separates the display of content from the logic used to obtain and manipulate the content.

In a Model 2 application, requests from the client browser are passed to the controller. The controller performs any logic necessary to obtain the correct content for display.

它针对web而设计,让controller进行必要的程序之后,将资料塞进view去呈现。

正是我们server-side框架在做的事情。

也就是说,server-side目前只能实作Model 2;client-side可以实作Model 2,也可以实作MVC。

巨大的代价

web工程师最常碰的就是client-side跟server-side框架。结果整个业界把MVC跟Model 2混为一谈,都说成MVC。

这带来了什么后果呢?

MVC变成一个从初学者到业界工程师,永远说不清楚、下不了定义的名词。

这件事对于学习和讨论,造成了非常巨大的成本。(参考下方的Q1和Q2)

那该怎么办?

下次有初学者询问「什么是MVC」的时候,怎么回答才不会害他回家之后「越查资料越混乱」?

Rails is not MVC的作者提出了三种解决方法:

第一个方法是声称MVC已经从原始意义改变了,Model 2也可以称为MVC。如此一来,我们可以用「传统MVC」或「真MVC」来描述原始的MVC。这是现在普遍的作法,但我不认为改变定义是一个好主意。这几乎是越搞越乱。

第二个方法是到处推广Rails其实是Model 2,MVC就留给…MVC吧。这很困难,但至少能保持定义不变。

第三个是直接忽略这些混乱。管它那么多?

我个人觉得MVC这个词已经没救了,不管怎么解释都会带给别人混乱。

当对方同时学习client-side跟server-side时,混乱更强烈。

我选择这样回答:

MVC有分很多种喔!网路上全部没写清楚,你一定看不懂。

没关系,你只要知道View可以抽出来就好。

C跟M先别管,你先随便瞎搞吧。

Q&A

Q1: 怎么可能各大server-side framework都搞错?

确实有人脑袋清醒得很,它就是Python的Django。

Django的官方文件内根本没有「Controller」这个名词。

看看Django官网的常见问题:

Q: Django似乎是一个MVC框架,但你们把Controller命名为「View」,把View命名为「Template」。你们干嘛不用标淮命名啊?

A: (前略)…如果你真的很想要一个缩写,你就说Django是一个MTV框架吧。Model、Template、View。这样分比较有道理些。

Django不想变成搞乱MVC的帮凶,只好委屈地又发明了一个名词「MTV」。

Q2: 那client-side框架有受影响吗?

有。client-side框架也必须为MVC巨大误会浪费一堆时间解释。

看看Backbone.js官网的常见问答:

Backbone跟「传统MVC」的关联何在?

(上略)

…我们来比较一下Backbone跟像是Rails这种server-side MVC框架的差别…

(下略)

Backbone实作了「传统MVC」,却被迫用「传统MVC」来描述server-side的Model 2,然后花一堆篇幅解释。

Q3: 知道Model 2的存在又如何?我现在依然一片混乱!

没错,Model 2跟MVC都用到Model、Controller、View三个名词,所以看起来类似。

但是,我们不应该再把时间花在思考「MVC怎么如此难懂」。

我们讨论的重点,应该是「如何分辨MVC与Model 2」、「在server-side如何实作Model 2才漂亮」、「在client-side实作MVC跟Model 2的优劣分别何在」。

Q4: 好,那你现在回答我,「如何分辨MVC与Model 2」?

OK,就让我抛砖引玉一下。

分别谈谈Model、View、Controller吧:

View

Model 2: 不具有行为,只是等别人塞资料进去的模板(template)。

MVC: 具有监视Model的行为,并以此去改变呈现(presentation)。

两种View有没有很像?跟张飞、岳飞一样像。

看看Backbone.js官网的View范例。你server-side的View哪是长这样?


Controller

Model 2: 接收请求与参数,转交给Model处理,再把结果(最新的资料)塞进View。

MVC: 接收请求与参数,转交给Model处理。没其他事了。

两种Controller有没有很像?跟小狗、热狗一样像。

MVC的View跟Model 2的Controller可能还比较像一点。(随便说说,千万别这样类比。)

Model

Model 2: 接收Controller传来的参数,回传结果。

MVC: 接收Controller传来的参数,将结果通知View。

Model倒是有些类似。

总之,Model 2跟MVC除了三个部份的名字一样之外,没什么关联了。

来源:http://blog.turn.tw/?p=1539


优才学院

优才学院,国内唯一一家提供全栈工程师培训的在线教育平台,开设有Web、ios、JS方向全栈课程,目前已培养全栈工程师500+,他们就职于腾讯、百度、滴滴、美丽说、友宝、中青龙图、锤子科技、途牛等知名企业,并且大部分学员在其企业担任要职,自主创业者也不在少数。如果你想提升技能或者进入名企,欢迎参加优才学院全栈课程学习。

课程咨询QQ:15243649

点击阅读原文,了解全栈课程↓

以上是关于MVC是一个巨大误会的主要内容,如果未能解决你的问题,请参考以下文章

向 system.webServer.httpErrors 添加 401 自定义错误会导致“无法在 Web 服务器上开始调试”错误

如何使用 RestTemplate 在 Spring MVC 应用程序中访问来自(来自 Spring RESTful 服务)的巨大 JSON

回发后的 MVC3 RedirectToAction

优化巨大的 JSON 响应

Struts2是一个基于MVC设计模式的Web应用框架

iOS UIScrollView,我误会了啥?我无法让滚动视图滚动