|
锁定老贴子 主题:MVC的迷思
该帖已经被评为精华帖
|
|
|---|---|
| 作者 | 正文 |
|
时间:2004-07-18
这个贴子是从“代码擂台”转过来的。我想专门讨论一下这个问题。
MVC的概念已经深入人心,是经常被大家经常提到的法宝利器。 我感到有必要澄清MVC的概念和来龙去脉,以便大家有一个共识,有一个共同讨论的基础,以便能够把讨论更深入地进行下去,解决真正的问题,而不是在一些技术概念上绕圈子。 一般来说,我不喜欢在名词概念上做文章,发表看法和评论。因为有更多的真正有挑战性的问题需要解决。但通过这段时间的讨论,我感到一种这样的危险: 我们程序员是否过于迷信MVC之类的名词概念,是否可能因此而减弱了或丧失了独立思考的能力? 所以我甘冒天下之大不韪,直言不讳了。 先举一个例子。 很多程序员言必讲,“和页面显示相关的逻辑,只应该存在于View里面,而不应该存在于任何其它部分的代码里面。” 但很少有人真正思考,这个概念从何而来。大家隐约地觉得这个概念来自于MVC。但为什么会有这个概念?这个概念的真实来源是什么? 其实,MVC中关于View的原意是这么说的,“View里面只应该存在和显示有关的逻辑,而不应该存在任何其它的逻辑——比如访问数据库,调用业务逻辑之类”。 纠其源头,这是针对很多程序员在JSP中调用JDBC的现象。 大家仔细比较一下这两句话的区别。可以看出对一个概念的执著和崇拜能够达到怎样的一种潜移默化的思维效果。 本意是为了降低View的作用,只让View做这一件事情,不让View做越权的事情。结果成为:只有View才能做这件事情,其它部分没有权利做这件事情。 那么我们来看,所有的MVC框架中,View部分做到了“只和显示逻辑相关” 吗?View能够脱离数据部分单独存在吗?不管是用JSP,Velocity,还是用TagLib,View都必须知道自己所使用的Object的数据结构,必须访问这些Object的各种属性,才能把它们显示出来。这个View和Model分开了吗?能分开吗? 从概念来讲,MVC是一个完备的概念吗?能够自圆其说吗? Struts是最流行的Web框架,也正是Struts令MVC概念风靡世界,成为Web程序员的圣经。 下面,我们来确认一下什么是MVC和MVC的来龙去脉。 MVC要求,Model把数据填充到request.attribute里面,通过Controller转发,View再把这些数据从request.attribute里面拽出来显示。 为什么需要这个过程呢?不知道大家想过这个问题吗?更深一步,有没有想过为什么Servlet规范需要request.attribute这个定义呢? 因为你没有别的方式把数据从Model传到View里面去。 MVC是为了解决JSP的天生缺陷而引入(原文为创造,错误)的。因为JSP是Servlet。你必须请求Web Server帮你定位并调用JSP/Servlet。 你必须调用 request.getRequestDispatcher("your.jsp").include(). 既然如此,如何在Servlet之间传输数据?只能通过request.attribute。 Velocity本来和MVC毫无关系,你完全可以在Action里面直接定位调用Velocity Template。 但为了支持MVC,Velocity不得已做了妥协,做了Velocity-tools,来支持MVC。 有兴趣请阅读org.apache.velocity.tools.view.servlet的 VelocityViewServlet类的代码。 你可以看到,Velocity是如何支持MVC的,付出了如何的代价。 Servlet规范又付出了怎样的代价。 参见VelocityViewServlet类的一段代码。 代码: [code:1] * @return Velocity Template object or null */ protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) throws Exception { // If we get here from RequestDispatcher.include(), getServletPath() // will return the original (wrong) URI requested. The following special // attribute holds the correct path. See section 8.3 of the Servlet // 2.3 specification. String path = (String)request.getAttribute("javax.servlet.include.servlet_path"); if (path == null) { path = request.getServletPath(); } return getTemplate(path); } [/code:1] fastm不具有JSP + TagLib的缺陷,没有需要MVC结构的根本需求。 我只把MVC看作一种可供参考的架构,从来不认为MVC是圣经。既然fastm本身就是离经叛道的。 下面我们探究一下,fastm的Data和View分离做的更好?还是MVC的Data和View分离做的更好? MVC的View需要了解处理各种类型的Data Object。MVC的View需要知道它们的属性名,甚至需要知道这些Data Object的属性代表什么意义,根据这些属性的值,决定怎样的显示方式(比如,赤字,还是蓝字)。这不是业务逻辑是什么? fastm的View(我是指Template DOM)只需要处理一种类型的Data Object – ValueSet DOM。ValueSet DOM本身就是数据和模板之间的桥梁,ValueSet DOM同时存放了数据之间的层次关系和数据本身,这正是DOM结构的精华所在。 另外,还有一个情况就是,似乎很少有人认识到DOM概念的重要性,大部分人都执著于Page Scripting技术(JSP,Velocity)。 另一个很古怪的现象就是,TagLib和Page Compent的概念,天生就是和Page Scripting技术(JSP,Velocity)技术 是对立的思路,却共存在View中,也从来没有人质疑。大家都把这当作一种经典思路,努力消化接受了,还研究颇深。其实这不过是 技术自身“修修补补”的结果而已。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2004-07-18
Web 表示层开发框架要解决好两方面的问题:
1、表示逻辑与业务逻辑的分离,以便实现细粒度的重用和组件化开发。 解决这个问题不一定非要使用 MVC。我们现在不更新页面时在浏览器/服务器之间传递的全部是 XML 格式的纯数据,与显示格式没有任何关系,显示格式完全由 JS 根据当时的语境自己决定。我认为我们已经很好地实现了表示逻辑与业务逻辑的分离。 2、提供丰富的控件帮助开发人员建造出表现能力丰富的 Rich Client。 这个问题目前各种流行的 Java Web 开发框架做的都是很不够的(可能 Tapestry 能好一些)。为什么?因为设计这些框架的人知识上存在盲区,不知道 JS 能做什么,完全忽视了浏览器端脚本的处理能力。认为所有表示层的问题都可以在服务器端解决掉,因此不需要 JS 的参与。 第二个问题甚至是更重要的问题,解决的难度比第一个问题要大的多。第二个问题不解决好,你就永远无法说服客户你们的产品确实比那个 xx 鸟公司的产品强。 其实一个很简单的 MVC 框架我最多半天时间就可以写出来,呵呵。 |
|
| 返回顶楼 | |
|
时间:2004-07-18
dlee 写道 Web 表示层开发框架要解决好两方面的问题:
2、提供丰富的控件帮助开发人员建造出表现能力丰富的 Rich Client。 这个问题目前各种流行的 Java Web 开发框架做的都是很不够的(可能 Tapestry 能好一些)。为什么?因为设计这些框架的人知识上存在盲区,不知道 JS 能做什么,完全忽视了浏览器端脚本的处理能力。认为所有表示层的问题都可以在服务器端解决掉,因此不需要 JS 的参与。 第二个问题甚至是更重要的问题,解决的难度比第一个问题要大的多。第二个问题不解决好,你就永远无法说服客户你们的产品确实比那个 xx 鸟公司的产品强。 其实一个很简单的 MVC 框架我最多半天时间就可以写出来,呵呵。 没错。 在B/S系统中,java script是成功的关键。尤其是在用户面前演示的时候。 我没有设计完备框架的能力,但我确实在Java Script知识上存在盲区。 而这个盲区不是通过系统学习克服的,必须通过实际经验。 所以,我一直觉得,Java Script高手,比Java高手要难得的多。 能不能讨论一下Java Script修炼的心得? |
|
| 返回顶楼 | |
|
时间:2004-07-18
buaawhl 写道 能不能讨论一下Java Script修炼的心得?
可能很多真正的 JavaScript 高手都是从这本书起步的: O'Reilly 的《JavaScript 权威指南》 http://sh.dearbook.com.cn/book/viewbook.aspx?pno=TS00644
Have fun! |
|
| 返回顶楼 | |
|
时间:2004-07-18
dlee 写道 buaawhl 写道 能不能讨论一下Java Script修炼的心得?
可能很多真正的 JavaScript 高手都是从这本书起步的: O'Reilly 的《JavaScript 权威指南》 http://sh.dearbook.com.cn/book/viewbook.aspx?pno=TS00644
Have fun! 定价:99.0元 售价:75.2元 内容简介: Java Script是一种功能强大的基于对象的脚本语言。Java Script程序可以直接嵌入HTML页面。与Web浏览器定义的文档对象模型(DOM)一起使用时,JavaScript可以创建动态HTML(DHTML)内容,允许用户与客户端的Web应用程序交互。... 《JavaScript权威指南》全面介绍了JavaScript语言的核心,以及Web浏览器中实现的遗留和标准的DOM。它运用了一些复杂的例子,说明如何处理验证表单数据、使用cookie、创建可移植的DHTML动画等常见任务。本书还包括详细的参考手册,涵盖了JavaScript的核心API、遗留的客户端API和W3C标准DOM API,记述了这些API中的每一个JavaScript对象、方法、性质、构造函数、常量和事件处理程序。 JavaScript 1.5(ECMAScript Version 3)的详细介绍。它还提供了W3C DOM标准(1级和2级)的完整内容,为了向后兼容,本书保持了遗留的O级DOM的资料。 多谢。 不错,就是贵了些。 不过对成为Java Script高手来说,这点代价也不算什么。 我读过ECMAScript规范等免费资料。 |
|
| 返回顶楼 | |
|
时间:2004-07-18
任何一种模式实际上都是为了减少反复考虑同一个问题而存在的。这样的好处不言自明,但是不适当的场合或者实现不够充分都会带来新的问题。
servlet本身其实就可以算作是一种MVC模式。所以对于Structs这样的薄层封装,我认为没有太大的进步。相反我认为struts 80%的作用在于提供的taglib,tile, validation,或许也有用。至于其他一些可配置,可管理的功能,的确没有带来很多的作用,相反人们诟病最多的就是源至于此。 一个MVC的实现,其实就是C的实现,以及让人们容易接受的从M到V的桥梁。struts(包括servlet)的实现不是很自然。纯数据有一些天然优势,借助于人的思维定势,但归纳还是不可避免要发生的。 |
|
| 返回顶楼 | |
|
时间:2004-07-18
MVC的起源和Java一点关系都没有,最早应该是80年代初期,第一篇真正的论文是smalltalk界面构造
|
|
| 返回顶楼 | |
|
时间:2004-07-18
buaawhl,
你的帖子里面有一些误区: 1. MVC并不是什么新东西,我第一次接触这个概念是在读大学的时候看SmallTalk的书里了解到的,我记得书上说是80年代出来的概念. 2. 不是Struts让MVC概念在B/S应用程序的架构里面流行起来的, 在我接触jsp以前, 我98年的时候看过php和asp也有人在用MVC的方式做项目,struts只是由于它是第一个浮出水面的open source jsp MVC架构,所以才会流行起来. 3. 你对于Velocity, Freemarker等模板技术的理解有误,如果是使用这些技术的话,Controller负责准备好Model, 将他们传递给模板进行渲染, 你可以直接输到客户端, 并不一定要通过Httprequest.setAttribute的方式.你举得例子我不明白要说明什么, 看上去是VelocityViewServlet如何获得模板所在的位置,这部分有什么问题吗? 4.我觉得MVC不是什么高深的模式,它是蛮容易理解的概念,我说过用100来行代码就可以写一个不错的WEB MVC架构,不是大家都把MVC看成是什么圣经,它只是一个工具而已. 然后对于你的fastm的建议: 我觉得fastm的竞争对手是freemarker, velocity等模板语言在View层的展现,而不是整个MVC架构. 那种把数据库链接, 复杂的逻辑判断都放在JSP里面的做法,现在应该没有什么人这样做了, fastm没有必要和这些不恰当的开发方法做比较. 而MVC架构的这么多年的存在和一直不断地发展必然有它的道理.希望你能够看看大家相关的讨论,让你的fastm发展得更好. Good Luck! |
|
| 返回顶楼 | |
|
时间:2004-07-18
potian 写道 MVC的起源和Java一点关系都没有,最早应该是80年代初期,第一篇真正的论文是smalltalk界面构造
回了一个长贴,发现potian抢在我前面说了......,看来我的记忆还不错,记得是80年代, |
|
| 返回顶楼 | |
|
时间:2004-07-18
Quake Wang 写道 buaawhl,
你的帖子里面有一些误区: 1. MVC并不是什么新东西,我第一次接触这个概念是在读大学的时候看SmallTalk的书里了解到的,我记得书上说是80年代出来的概念. 2. 不是Struts让MVC概念在B/S应用程序的架构里面流行起来的, 在我接触jsp以前, 我98年的时候看过php和asp也有人在用MVC的方式做项目,struts只是由于它是第一个浮出水面的open source jsp MVC架构,所以才会流行起来. 3. 你对于Velocity, Freemarker等模板技术的理解有误,如果是使用这些技术的话,Controller负责准备好Model, 将他们传递给模板进行渲染, 你可以直接输到客户端, 并不一定要通过Httprequest.setAttribute的方式.你举得例子我不明白要说明什么, 看上去是VelocityViewServlet如何获得模板所在的位置,这部分有什么问题吗? 4.我觉得MVC不是什么高深的模式,它是蛮容易理解的概念,我说过用100来行代码就可以写一个不错的WEB MVC架构,不是大家都把MVC看成是什么圣经,它只是一个工具而已. 然后对于你的fastm的建议: 我觉得fastm的竞争对手是freemarker, velocity等模板语言在View层的展现,而不是整个MVC架构. 那种把数据库链接, 复杂的逻辑判断都放在JSP里面的做法,现在应该没有什么人这样做了, fastm没有必要和这些不恰当的开发方法做比较. 而MVC架构的这么多年的存在和一直不断地发展必然有它的道理.希望你能够看看大家相关的讨论,让你的fastm发展得更好. Good Luck! 哦。我犯了一个大错误。多谢指正。也多谢其他人的指正。 我只知道MVC在Struts,Maverick,Spring等Web Framework中的实现。 你分析的没错。fastm的竞争对手是freemarker, velocity等模板语言在View层的展现,而不是整个MVC架构. 没错,我知道Velocity, Freemarker等模板技术,和fastm一样,可以直接输到客户端。 但VelocityViewServlet就是为了衔接Strusts等MVC框架的。 你在web.xml里面配置。 <servlet> <servlet-name>velocity</servlet-name> <servlet-class> org.apache.velocity.tools.view.servlet.VelocityViewServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>velocity</servlet-name> <url-pattern>*.vm</url-pattern> </servlet-mapping> 然后调用,request.getRequestDispatcher("your.vm").include(); 然后,Web Server帮助你调用VelocityViewServlet类。 我是说,Velocity本来可以直接用的,但为了支持MVC,却非要多出来这一步。 |
|
| 返回顶楼 | |









