`
liujiboy
  • 浏览: 13905 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Ajax把MVC模式变成了"MV模式"

阅读更多

请暂且原谅本人的浅薄,原来有一篇blog写到我初次接触ajax觉得这玩意不过如此。如今本人却要来一个180度的转弯了,大家不要笑话,人认识事物是渐进的啊

最近才认真学习了ajax,目前已经在项目中应用了,感觉很好。我想大家都知道ajax的基本原理的,在此就不多说了。从这段时间的实践来看。我认为采用了ajax的网站,完全可以从MVC模式变为MV模式。

什么是MV模式,这是我的一个提法,只是把c给去掉了,相信很多人都有同样的想法,也许我有幸成为世界上第一个采用这一个名称的人。至少我在google上面没有查到有人用这个说法。所谓MV就是模型-视图模式。大家也许记得为什么当初要发明MVC模式。MVC的目的是为了实现表示层逻辑和业务逻辑的分离。这种分离的代价在当时的技术条件下,就是产生了称为controller的玩意。

只要写过struts的人都一定知道,虽然struts可以实现表示层逻辑和业务逻辑的分离,但这种分离是让人非常不愉快的。首先我们需要继承Action类,然后在这个类中写控制代码,最后有一个叫struts-config.xml的文件等待我们去配置。struts的controller是很难设计的,首先配置比较复杂。xml的配置文件毕竟是一个额外的文件,配置文件的确有好处,但如何维护配置文件是一个问题,如果你的项目中有人不小心错改了配置文件,恭喜你一个隐藏的bug就出现了。当然这不是struts的controller的罪恶,更不是MVC的错。更大的问题还在后面,那就是如何设计controller控制的粒度。有的人会写一个非常big的controller,用这个controller来控制N个页面(汗一个)。有人会为每一个页面产生一个controller,结果controller泛滥。有人不知道controller是干嘛的于是什么代码都往里面写,什么权限验证、数据验证、页面跳转、页面数据设置、业务逻辑、事物控制、数据库连接都往里面放!(好像有的东西的确应该往里面放)。

也就是说在使用controller的情况下,几乎很难把controller设计得很好,当然有人可以设计得很好,但既然不是大多数人,那么我有理由说controller的技术是有缺陷的。其实产生这一问题的原因很简单,controller是联系表示与业务的纽带,也就通讯员。通讯员该干什么,干多少,很容易搞混淆啊。哦,上面说的是struts的controller,webwork和spring的要好一些,struts的controller还不好单元测试(历史原因历史原因)

总结一下,MVC模式中的C存在的问题:

1.通常需要配置,比较麻烦

2.设计的粒度不会控制

3.该干什么事情容易搞错

4.部分controller难以单元测试

有这些问题自然要想一想,如果没有controller,行不行?

答案是这样的,在有了Ajax之后,controller终于可以不要了!

目前我使用的Ajax框架是DWR,通过使用DWR,controller的确是彻底去掉了。

怎么去掉的?我其实也没有刻意为之,只是DWR的工作模式本来就是这样的。。。DWR可以让客户端的Javascript直接访问远程的一个Java对象。也就是说表示层直接访问业务层。但是慢着,这并没有带来耦合。表示还是那个表示,业务还是那个业务,女人还是那个女人,狗还是。。。

我实在想不出使用DWR的情况下有什么理由要设计一个controller。

啊,好像还真有那么一点情况,客户端不支持Javascript。。。这种情况下,老实的搞MVC吧,但是不支持Ajax的浏览器挺少的。

还有吗?啊好像还有一个问题。如果想在业务方法中,访问session,request等对象如何办呢?比如要做一个购物车,购物车存放在session里面。这个问题吗?没有难住我,你可以存到数据库里面啊!啊!啊!不要扔臭鸡蛋!好了,好了我告诉你我有一个设计方法可以很好的解决这个问题,不仅不会在业务层嵌入任何与Web相关的对象,而且表示还是表示,业务还是业务,女人还是女人,狗还是。。。没有一点杂交的。但是这里的纸太小了,我写不下(偷偷说一句,其实不难啊)

也许有人提出MV模式实际还是MVC的,比如DWR就配置了一个servlet,这个servlet其实就是C

这要看你如何看待这个问题了。其实任何模式最后都是010101,因此任何模式实际都是一个模式。。。

为什么提出MV模式,我认为主要是为大家提供一种设计思路,MV模式的确带来了一些不同于MVC模式的思维方式。其实MV和MVC也不是矛盾的,大家灵活应用就是了。

最后,今后我们是不是可以多一个术语MV模式呢?

分享到:
评论
16 楼 ray_linn 2007-01-06  
liujiboy 写道
解释一下GUI中采用MV可能产生耦合的情况,以我自己的编程经验来说,GUI中采用MV必然导致紧密耦合。请注意,什么是M,什么是V,什么是C。例如一个Swing中的JButton。JButton显示出来就是一个按键,当我对JButton进行点击时,请注意,按键获得了焦点,并且形态要发生一定的变化(通常按键显示出一种凹陷的感觉,并且有黑色的虚线边框,不知道button发生了什么变化的人,按一下按键看看)。
我们来分析一下这个过程。负责显示按键形态的部分显然是V了,记录按键是否获得焦点的一定就是那个M了,那么谁告诉M应该改变状态值,谁又告诉V需要重绘呢?显然是那个C了。
有人说你简直是强词夺理,有这么复杂吗?告诉你JButton是一个对象,对象里面的一个变量记录按键的状态,然后JButton负责重绘。这只是对象的封装,连MV都算不上,怎么扯到MVC上面去了!
冷静点,打开编辑器,调出JButton的代码,看看你说的那个记录按键状态的变量叫什么名字——model!仔细看,model还是一个对象,叫ButtonModel。再看看是如何重绘的。repaint没错吧,repaint之后实际产生作用的是paint,paint是如何画按键的?提示一下有一个叫ButtonUI的玩意,还有一个叫Graphics的玩意。
种种迹象表明Java的Swing是MVC模式的。在JButton这个类中,JButton既不是View,也不是Model,而是一个Controller。在经典的MVC模型中Controller拦截并处理前端的请求,JButton可以说是非常经典。认为JButton不是Controller的实际是被JButton的名字给蒙骗了。
回答GUI中采用MV导致耦合的情况。按照MV的思路也就是将JButton这个对象去掉,将ButtonModel和ButtonUI直接联系起来,会发生什么情况呢?大家不妨把ButtonModel和ButtonUI直接连接起来看看是不是有一个类一下子就变臃肿了,原来不该它干的好多事情需要它来干了。


你要是这么理解就没什么好谈的了,撤退~~~~
15 楼 liujiboy 2007-01-06  
kenken0y 写道
正统的MVC中是把V作为M的Observer,一个变形是模型代理结构(Model-Delegate),代理既提供模型的表现,同时也提供接口用于改变模型,实际上是V和C合并在一起了。M-D有点像lz所说的MV。

一般在web中M和V却是完全隔离的,因为M无法通知V自己改变了。

使用ajax时具体是怎么回事要看传回来的内容,以DWR为例,如果传回来的是json对象,还是需要对页面赋值,这些代码起的就是C的作用呀;如果穿回来的是js语句(在java代码中用DWRUtil.setValues,实际传回的是js,传回后会被直接eval),这种情况下browse端的M和C都不见了,讨论没有意义了。服务器端如果分得比较细的话,可以用java实现MVC,实际V可以被封装,这样写的话可以在web上实现真正的MVC了(M对V的通知可以利用DWREngine.setReverseAjax(true))。

用ajax时服务器端的C还是少不了的吧,否则session怎么处理?难道dwr直接调用manager?session怎么处理,不会出现在manager的方法的参数中吧

取消C之后最大的问题就是如何处理Session等Web元素,但实际上这个问题是比较容易解决。
我的项目已经解决了这个问题,而且非常漂亮。改天我整理一下思路,发给大家分享。
14 楼 kenken0y 2007-01-06  
正统的MVC中是把V作为M的Observer,一个变形是模型代理结构(Model-Delegate),代理既提供模型的表现,同时也提供接口用于改变模型,实际上是V和C合并在一起了。M-D有点像lz所说的MV。

一般在web中M和V却是完全隔离的,因为M无法通知V自己改变了。

使用ajax时具体是怎么回事要看传回来的内容,以DWR为例,如果传回来的是json对象,还是需要对页面赋值,这些代码起的就是C的作用呀;如果穿回来的是js语句(在java代码中用DWRUtil.setValues,实际传回的是js,传回后会被直接eval),这种情况下browse端的M和C都不见了,讨论没有意义了。服务器端如果分得比较细的话,可以用java实现MVC,实际V可以被封装,这样写的话可以在web上实现真正的MVC了(M对V的通知可以利用DWREngine.setReverseAjax(true))。

用ajax时服务器端的C还是少不了的吧,否则session怎么处理?难道dwr直接调用manager?session怎么处理,不会出现在manager的方法的参数中吧
13 楼 liujiboy 2007-01-05  
ray_linn 写道
liujiboy 写道
mv的说法肯定不是什么新玩意,现在又有几个计算机技术是新玩意?
在我以前的项目中我用其他手段也实现了和ajax一样的东西,按照这个说法ajax也不是什么新玩意。
也许是我没有说清楚,我的意思是:采用ajax开发网站,我们可以跳出原有的mvc的框框,采用mv的方式。而这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。
mv模式是我为了方便问题的说明下的一个定义,方便后文的引用。类似于“在下文中简称这种方式为MV”。



这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。 -----  什么叫混在一起?为什么就松耦合,为什么就是紧耦合? 是不是自己的编程思想有问题?


你列举的情况恰恰说明MVC的回归。从Front Controller或者page controller回归到“古典/经典MVC"因为XMLHTTP成为了可能---客户端可以发出视图事件给控制器,同时可能可以接受模型改变事件。(只是可能)。

解释一下GUI中采用MV可能产生耦合的情况,以我自己的编程经验来说,GUI中采用MV必然导致紧密耦合。请注意,什么是M,什么是V,什么是C。例如一个Swing中的JButton。JButton显示出来就是一个按键,当我对JButton进行点击时,请注意,按键获得了焦点,并且形态要发生一定的变化(通常按键显示出一种凹陷的感觉,并且有黑色的虚线边框,不知道button发生了什么变化的人,按一下按键看看)。
我们来分析一下这个过程。负责显示按键形态的部分显然是V了,记录按键是否获得焦点的一定就是那个M了,那么谁告诉M应该改变状态值,谁又告诉V需要重绘呢?显然是那个C了。
有人说你简直是强词夺理,有这么复杂吗?告诉你JButton是一个对象,对象里面的一个变量记录按键的状态,然后JButton负责重绘。这只是对象的封装,连MV都算不上,怎么扯到MVC上面去了!
冷静点,打开编辑器,调出JButton的代码,看看你说的那个记录按键状态的变量叫什么名字——model!仔细看,model还是一个对象,叫ButtonModel。再看看是如何重绘的。repaint没错吧,repaint之后实际产生作用的是paint,paint是如何画按键的?提示一下有一个叫ButtonUI的玩意,还有一个叫Graphics的玩意。
种种迹象表明Java的Swing是MVC模式的。在JButton这个类中,JButton既不是View,也不是Model,而是一个Controller。在经典的MVC模型中Controller拦截并处理前端的请求,JButton可以说是非常经典。认为JButton不是Controller的实际是被JButton的名字给蒙骗了。
回答GUI中采用MV导致耦合的情况。按照MV的思路也就是将JButton这个对象去掉,将ButtonModel和ButtonUI直接联系起来,会发生什么情况呢?大家不妨把ButtonModel和ButtonUI直接连接起来看看是不是有一个类一下子就变臃肿了,原来不该它干的好多事情需要它来干了。
12 楼 liujiboy 2007-01-05  
lane_cn 写道
你用Visual Studio 6.0做一个MFC窗体应用程序,用工程向导自动生成的框架就是一个Document加一个View,这就是MV模式。
现在谁的机器上装VS6了,试试看。
MV模式其实就是把Controller往View里面塞。
至于unit测试Controller,不知道你到底是在想什么。把Model和Controller、View分开的目的就在于他们混在一起,使得Model无法unit测试。分开了以后Model是绝对不能依赖Controller和View的,这就使得Model可以单独测试了。至于Controller和View,Controller不必测试,他只是一个传声筒;View搞单元测试,还不如直接用眼睛看一下。
如果你觉得你写的Controller和View需要测试,最好是先看看是不是你把很多Model该做的事情放错了地方。


我谈的MV是Web上面的,谈VC是否有些不恰当呢?其次VC中的Document加view的做法难道就是我说的MV吗?
你用VC建一个MFC工程,然后把View放在CView的子对象里面,把Model放在CDocument的子对象里面,我想问一下当你的Model越大的时候,你怎么办?你是继续派生一个CDocument以产生一个新的Document,还是选择新建一个C++类把Model封装在这个新类里面,然后让Document来调用这些Model呢?我选择后者,如果选择了后者Document的实际作用就是Controller。而且VC的设计难道很好吗?特别是VC的GUI,恐怕远没有Java设计得好。偷偷说一句很多C++程序员虽然不一定认为Java的GUI好,但一定不会认为vC的GUI是C++中最好的。
至于Controller和View的单元测试问题,你提出来用眼睛看比较方便,对这点我也曾经这么认为。但看了《JUnit in action》之后我发现书中很多地方在测试Controller和view。后来我转变了一下看法,如果一个项目是这么开发的:页面编写人员编写页面,业务逻辑编写人员编写业务逻辑。这两种开发是并行进行的,那么页面编写人员在编写完页面之后,难道不对页面测试吗?注意当页面编写人员完成页面编写的时候,业务逻辑还很可能没有写完,而且这个时候连接业务逻辑和页面的Controller肯定是没有写出来的。那么为什么要测Controller?就是因为存在设计臃肿的Controller,一个Controller只有一个两种分支情况你可以用眼睛去看,如果一个Controller庞大到要控制五、六种跳转逻辑(还不包括其他逻辑),你是否能够靠眼睛去看呢?
在我看来单元测试的最大优势是测试的自动化和测试的可重复性。按照很多项目实践Controller和View是完全有必要进行测试的。至于你说用眼睛就可以测试,一个只有"hello world"这样一行代码的View,是可以用眼睛来测试的。只不过,随着项目的进行,每进行一次修改你都要用眼睛去确认一下这个View是不是正确显示了hello world(完全可能显示成了HELLO WORLD),是不是有点麻烦?
View和Controller不是需不需要单元测试,而是如何测试的问题。如果能够雇一帮人不断的为你的View和Controller采用眼睛扫描的方式进行测试,这实际也是在单元测试,只是这个单元测试不是用计算机,而且成本有点高,并且人的眼睛犯错误的几率比较高哦。
11 楼 ray_linn 2007-01-05  
总得看来,你把Webwork和Struts的MVC当成了唯一的MVC了,他们这种古怪的设计只是因为HTTP的特点而已--因为HTTP 1.0的请求/响应的特点(无状态连接),模型的变更没办法"推"(或者通知)到View端了. 由于浏览器五花八门的, 不能要求他们统统支持http 1.1,所以只好采用挖洞的办法, 设计个组件放到Browser里保持连接.这个组件就是XMLHTTP.

AJAX的最大特点是什么,是异步更新,核心是什么,XMLHTTPREQUEST,关键事件是什么 OnReadyStateChange嘛. (我猜)由于XMLHTTPREQUEST保持了与服务器的连接,不信你用TCPDUMP抓一下,里面可能有这样些东西( Keep-Alive: timeout=15, max=99 Connection) 所以接受model的更新事件成为了可能.

假设:view.jsp(视图)、action.do(控制器)、model.java(模型)

view.jsp是用户看到的界面,并通过内置的AJAX对象异步方式给action.do发送请求,AJAX.OnReadyStateChange开始监听(其实就是看看HTTP包头吧).

action.do接收到view.jsp发过来的请求(GET或者POST方式),通过Request判断后发送给相应的业务/数据模型model.java

model.java开始执行业务操作,执行完毕直接给view.jsp页面发送数据更新的通知,这个通知的消息有可能是XML封装的数据。

view.jsp页面中AJAX对象的OnReadyStateChange接收到了数据更新通知,根据实际情况用DOM进行页面呈现更新。

正是基于上述理由,我说XMLHTTP可能把Web MVC带回经典MVC的状态.

PS: 我一篇AJAX的文章都没看过的,纯属想像, onReadyStateChange这个词儿是现查的,所以说错了请拍砖.


10 楼 lane_cn 2007-01-05  
你用Visual Studio 6.0做一个MFC窗体应用程序,用工程向导自动生成的框架就是一个Document加一个View,这就是MV模式。
现在谁的机器上装VS6了,试试看。
MV模式其实就是把Controller往View里面塞。
至于unit测试Controller,不知道你到底是在想什么。把Model和Controller、View分开的目的就在于他们混在一起,使得Model无法unit测试。分开了以后Model是绝对不能依赖Controller和View的,这就使得Model可以单独测试了。至于Controller和View,Controller不必测试,他只是一个传声筒;View搞单元测试,还不如直接用眼睛看一下。
如果你觉得你写的Controller和View需要测试,最好是先看看是不是你把很多Model该做的事情放错了地方。
9 楼 dwangel 2007-01-05  
我觉得是其实没有改变mvc模式,只是不需要自己写controller了。
8 楼 ray_linn 2007-01-05  
liujiboy 写道
mv的说法肯定不是什么新玩意,现在又有几个计算机技术是新玩意?
在我以前的项目中我用其他手段也实现了和ajax一样的东西,按照这个说法ajax也不是什么新玩意。
也许是我没有说清楚,我的意思是:采用ajax开发网站,我们可以跳出原有的mvc的框框,采用mv的方式。而这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。
mv模式是我为了方便问题的说明下的一个定义,方便后文的引用。类似于“在下文中简称这种方式为MV”。



这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。 -----  什么叫混在一起?为什么就松耦合,为什么就是紧耦合? 是不是自己的编程思想有问题?


你列举的情况恰恰说明MVC的回归。从Front Controller或者page controller回归到“古典/经典MVC"因为XMLHTTP成为了可能---客户端可以发出视图事件给控制器,同时可能可以接受模型改变事件。(只是可能)。
7 楼 抛出异常的爱 2007-01-05  
liujiboy 写道
引用

MV 模式,不是你的新玩意儿。。。那不就是Document 模式嘛。VB、ASP.net上比比皆是。

你的说法其实就是就是ajax让web更象VB罢鸟。


mv的说法肯定不是什么新玩意,现在又有几个计算机技术是新玩意?
在我以前的项目中我用其他手段也实现了和ajax一样的东西,按照这个说法ajax也不是什么新玩意。
也许是我没有说清楚,我的意思是:采用ajax开发网站,我们可以跳出原有的mvc的框框,采用mv的方式。而这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。
mv模式是我为了方便问题的说明下的一个定义,方便后文的引用。类似于“在下文中简称这种方式为MV”。

引用

tiyi 10 小时前
没有用户代码,不代表该框架角色不存在

对于这个问题,我已经解释了,对于DWR等框架Controller是存在的。但对于我们使用框架的人来说,Controller是不存在的。就好比使用高级语言编程的人,从来不会考虑机器语言。谈论mvc模式的时候,也不会考虑图灵机模型。


我也只看了几天的ajax还没用到项目中有以下几点看法
1.本身ajax不是java专用技术(不用java也能实现)
2.ajax减少了页面的总量。。。(很多功能在同一个页面内完成)
3.ajax不包括在mvc架构中而是一种web的C/S的变型。。。。(如果加上DWR的话才像点MVC)
4.ajax提出了一种新的开发方式。。。(使学习css成为程序员必修课)
6 楼 liujiboy 2007-01-05  
引用

MV 模式,不是你的新玩意儿。。。那不就是Document 模式嘛。VB、ASP.net上比比皆是。

你的说法其实就是就是ajax让web更象VB罢鸟。


mv的说法肯定不是什么新玩意,现在又有几个计算机技术是新玩意?
在我以前的项目中我用其他手段也实现了和ajax一样的东西,按照这个说法ajax也不是什么新玩意。
也许是我没有说清楚,我的意思是:采用ajax开发网站,我们可以跳出原有的mvc的框框,采用mv的方式。而这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。
mv模式是我为了方便问题的说明下的一个定义,方便后文的引用。类似于“在下文中简称这种方式为MV”。

引用

tiyi 10 小时前
没有用户代码,不代表该框架角色不存在

对于这个问题,我已经解释了,对于DWR等框架Controller是存在的。但对于我们使用框架的人来说,Controller是不存在的。就好比使用高级语言编程的人,从来不会考虑机器语言。谈论mvc模式的时候,也不会考虑图灵机模型。
5 楼 liujiboy 2007-01-05  
MV 模式,不是你的新玩意儿。。。那不就是Document 模式嘛。VB、ASP.net上比比皆是。

你的说法其实就是就是ajax让web更象VB罢鸟。
引用

mv的说法肯定不是什么新玩意,现在又有几个计算机技术是新玩意?
在我以前的项目中我用其他手段也实现了和ajax一样的东西,按照这个说法ajax也不是什么新玩意。
也许是我没有说清楚,我的意思是:采用ajax开发网站,我们可以跳出原有的mvc的框框,采用mv的方式。而这种方式和GUI程序中model和view混杂在一起的编程方式也有不同。这种网站开发中的mv模式,它是松散耦合的,而GUI程序中的mv是紧密耦合的。
mv模式是我为了方便问题的说明下的一个定义,方便后文的引用。类似于“在下文中简称这种方式为MV”。
tiyi     10 小时前
没有用户代码,不代表该框架角色不存在
引用

对于这个问题,我已经解释了,对于DWR等框架Controller是存在的。但对于我们使用框架的人来说,Controller是不存在的。就好比使用高级语言编程的人,从来不会考虑机器语言。谈论mvc模式的时候,也不会考虑图灵机模型。
4 楼 ray_linn 2007-01-05  
MV 模式,不是你的新玩意儿。。。那不就是Document 模式嘛。VB、ASP.net上比比皆是。

你的说法其实就是就是ajax让web更象VB罢鸟。
3 楼 歆渊 2007-01-05  
我觉得 controller 的意义在于把分散的请求集中到一个通道中, 从而能透明的应用一些通用的 过滤/包装/预处理/后处理 逻辑, 达到重用这些逻辑的目的, 和AOP的思想和目标有些类似.

不用AJAX其实也能去掉 controller, 每个页面分别提交到不同 URL 就行了. AJAX 的结果是一个 "页面" 中天生可以有多个目标URL, 各自用途也不一样, 所以更容易让人想到指向不同的地址.
2 楼 kdekid 2007-01-05  
这只是 event-driven 的 UI programming,早就有了。
1 楼 tiyi 2007-01-05  
没有用户代码,不代表该框架角色不存在

相关推荐

Global site tag (gtag.js) - Google Analytics