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