大型JavaScript应用程序架构模式.pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《大型JavaScript应用程序架构模式.pdf》由会员分享,可在线阅读,更多相关《大型JavaScript应用程序架构模式.pdf(18页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、大型大型 JavaScriptJavaScript 应用程序架构模式应用程序架构模式 2011-12-14 21:13:50 11 月中旬在伦敦举行的 jQuery Summit 顶级大会上有个 session 讲的是大型JavaScript 应用程序架构,看完 PPT 以后觉得甚是不错,于是整理一下发给大家共勉。PDF 版的 PPT 下载地址:http:/ 注:在整理的过程中,发现作者有些思想是返来复去地说,所以删减了一部分,如注:在整理的过程中,发现作者有些思想是返来复去地说,所以删减了一部分,如果你的英文良好,请直接阅读英文的果你的英文良好,请直接阅读英文的 PPTPPT。什么叫什么叫“
2、JavaScript 大型程序大型程序”?在我们开始之前,我们来定义一下什么叫大型 JavaScript 站点,很多有经验的 JS开发高手也都被 challenge 住了,有人说超过 10 万行 JavaScript 代码才算大型,也有人说 JavaScript 代码要超过 1MB 大小才算,其实 2 者都不能算对,因为不能安装代码量的多少来衡量,很多琐碎的 JS 代码很容易超过 10 万行的。我对“大”的定义如下,虽然可能不太对,但是应该是比较接近了:我个人认为,大型我个人认为,大型 JavaScript 程序应该是非常重要并且融入了很多卓越开发人员努力,对程序应该是非常重要并且融入了很多卓
3、越开发人员努力,对重量级数据进行处理并且展示给重量级数据进行处理并且展示给浏览器浏览器的程序。的程序。回顾当前的程序架构回顾当前的程序架构 我不能强调说这个问题有多重要,很多有经验的开发人员经常说:“现有的创意和设计模式在我上一个中型项目上运行得非常好,所以在稍微大型点的程序里再次使用,应该没问题,对吧?”,在一定程序上是没错的,但别忘记了,既然是大型程序,通常就应该有大的 Concerns 需要分解关注,我简短解释一下要花时间来 review 当前运行了很久的程序架构。大多数情况下,当前的 JavaScript 程序架构应该是如下这个样子的(注意,是 JS 架构,不是大家常说的 ASP.NE
4、T MVC):custom widgets models views controllers templates libraries/toolkits an application core.你可能还会将程序单独封装成多个 modules,或者使用其他的设计模式,这很好,但是如果这些结构完全代表你的架构的话,就可能会有一些潜在的问题,我们来看看几个重要的点:1.1.你架构里的东西,有多少可以立即拿出来重用?你架构里的东西,有多少可以立即拿出来重用?有没有一些单独的 module 不依赖别的代码?是自包含么?如果我到你们正在使用的代码库上去随即挑选一些模块 module 代码,然后放在一个新页面
5、,是否能立即就能使用?你可能会说原理通就可以了,我建议你长久打算一下,如果你的公司之前开发很多重要的程序,突然有一天有人说,这个项目里的聊天模块不错,我们拿出来放在另外一个项目里吧,你能直接拿过来不修改代码就能使用么?2.2.系统里有多少模块系统里有多少模块 modulemodule 需要依赖其他模块?需要依赖其他模块?系统的各个模块是不是都很紧耦合?在我将这个问题作为 concern 之前,我先解释一下,不是说所有的模块都绝对不能有任何依赖,比如一个细粒度的功能可能是从base 功能扩展来的,我的问题和这种情况不一样,我说的是不同功能模块之前的依赖,理论上,所有的不同功能模块都不应该有太多的
6、依赖。3.3.如果你程序的某一部分出错了,其他部分是否能够依然工作?如果你程序的某一部分出错了,其他部分是否能够依然工作?如果你构建一个和 Gmail 差不多的程序,你可以发现 Gmail 里很多模块都是动态加载的,比如聊天 chat 模块,在初始化页面的时候是不加载的,而且就算加载以后出错了,页面的其他部分也能正常使用。4.4.你的各个模块你的各个模块 ModuleModule 能很简单的进行测试么?能很简单的进行测试么?你的每一个模块都有可能用在数百万用户的大型站点上,甚至多个站点都使用它,所以你的模块需要能经得住测试,也就是说,不管是在架构内部还是架构外部,都应该能很简单的去测试,包括大
7、部分的断言在不同的环境下都能够通过。长远考虑长远考虑 架构大型程序的时候,最重要的是要有前瞻性,不能只考虑一个月或者一年以后的情况,要考虑更长久的情况下,有什么改变的可能性?开发人员经常将 DOM 操作的代码和程序绑定得太紧,尽管有时候已经封装单独的逻辑到不同的模块里了,想想一下,长久以后,为什么不是很好。我的一个同事曾经说过,一个精确的架构可能不适合未来的情景,有时候是正确的,但是当你需要该做的话,你所付出的 money 那可是相当地多哦。比如,你可能因为某些性能,安全,设计的原因需要在 Dojo,jQuery,Zepto,YUI 之间需要选择替换,这时候就有问题了,大部分模块都有依赖,需要
8、钱呀,需要时间啊,需要人呀,对不?对于一些小型站点没事,但是大型站点确实需要提供一个更加灵活的机制,而不去担心各个模块之间的各种问题,这既然节约钱,又能节约时间。总结一下,现在你能确定你能不重写整个程序就能替换一些类库么?如果不能,那估计我们下面要讲的内容,就比较适合你了。很多有经验的 JavaScript 开发者给出了一些关键的 notes:JavaScriptMVC 的作者 Justin Meyer 说:构建大型程序最大的秘密就是从来不构建大型程序,而是将程序分解成各个小的模块去做,让每个小模块都可测试,可 size 化,然后集成到程序里。High-performance JavaScri
9、pt websites 作者 Nicholas,Zakas:The key is to acknowledge from the start that you have no idea how this will grow.When you accept that you dont know everything,you begin to design the system defensively.You identify the key areas that may change,which often is very easy when you put a little bit of ti
10、me into it.For instance,you should expect that any part of the app that communicates with another system will likely change,so you need to abstract that away.-一大堆文字问题,太麻烦了,总结一句就是,一切皆可变,所以要抽象。jQuery Fundamentals 作者 Rebecca Murphey:各个模块之间联系的越密切,重用性越小,改变起来困难越大。以上这些重要观点,是构建架构的核心要素,我们需要时刻铭记。头脑风暴头脑风暴 我们来头
11、脑风暴一下,我们需要一个松耦合的架构,各模块之间没有依赖,各个模块和程序进行通信,然后中间层接管和处理反馈相应的消息。例如,我们如果有一个 JavaScript 构建在线面包店程序,一个模块发出了一个信息可能是“有 42 个圆面包需要派件”。我们使用不同的 layer 层来处理模块发来的消息,做到如下:1.模块不直接访问程序核心 2.模块不直接调用或影响其它的模块 这将防止我们因为某个模块出错,而导致所有的模块出错。另外一个问题是安全,真实的情况是,大多数人都不认为内部安全是个问题,我们自己心里说,程序是我自己构建的,我知道哪些是公开的那些私有的,安全没问题,但你有没有办法去定义哪个模块才能权
12、限访问程序核心?例如,有一个 chat 聊天模块,我不想让他调用 admin 模块,或者不想让它调用有 DB 写权限的模块,因为这之间存在很脆弱,很容易导致 XSS 攻击。每个模块不应该能做所有的事情,但是当前大多数架构里的 JavaScript 代码都有这种的问题。提供一个中间层来控制,哪个模块可以访问那个授权的部分,也就是说,该模块最多只能做到我们所授权的那部分。建议的架构建议的架构 我们本文的重点来了,这次我们提议的架构使用了我们都很熟知的设计模式:module,facade 和 mediator。和传统的模型不一样的是,为了解耦各个模块,我们只让模块发布一些 event 事件,medi
13、ator 模式可以负责从这些模块上订阅消息 message,然后控制通知的 response,facade 模式用户限制各模块的权限。以下是我们要注意讲解的部分:1 设计模式 1.1 模块论 1.1.1 综述 1.1.2 Module 模式 1.1.3 对象自面量 1.1.4 CommonJS 模块 1.2 Facade 模式 1.3 Mediator 模式 2 应用到你的架构 2.1 Facade-核心抽象 2.2 Mediator-程序核心 2.3 紧密联合运作起来 块论块论 大家可能都或多或少地使用了模块化的代码,模块是一个完整的强健程序架构的一部分,每个模块都是为了单独的目的为创建的,
14、回到 Gmail,我们来个例子,chat聊天模块看起来是个单独的一部分,其实它是有很多单独的子模块来构成,例如里面的表情模块其实就是单独的子模块,也被用到了发送邮件的窗口上。另外一个是模块可以动态加载,删除和替换。在 JavaScript 里,我们又几种方式来实现模块,大家熟知的是 module 模式和对象字面量,如果你已经熟悉这些,请忽略此小节,直接跳到 CommonJS 部分。ModuleModule 模式模式 module 模式是一个比较流行的设计模式,它可以通过大括号封装私有的变量,方法,状态的,通过包装这些内容,一般全局的对象不能直接访问,在这个设计模式里,只返回一个 API,其它的
15、内容全部被封装成私有的了。另外,这个模式和自执行的函数表达式比较相似,唯一的不同是 module 返回的是对象,而自执行函数表达式返回的是 function。众所周知,JavaScript 不想其它语言一样有访问修饰符,不能为每个字段或者方法声明 private,public 修饰符,那这个模式我们是如何实现的呢?那就是 return一个对象,里面包括一些公开的方法,这些方法有能力去调用内部的对象。看一下,下面的代码,这段代码是一个自执行代码,声明里包括了一个全局的对象basketModule,basket 数组是一个私有的,所以你的整个程序是不能访问这个私有数组的,同时我们 return 了
16、一个对象,其内包含了 3 个方法(例如addItem,getItemCount,getTotal),这 3 个方法可以访问私有的 basket 数组。 var basketModule=(function()var basket=;/private return /exposed to public addItem:function(values)basket.push(values);,getItemCount:function()return basket.length;,getTotal:function()var q=this.getItemCount(),p=0;while(q-)p
17、+=basketq.price;return p;();同时注意,我们 return 的对象直接赋值给了 basketModule,所以我们可以像下面一样使用:/basketModule is an object with properties which can also be methods basketModule.addItem(item:bread,price:0.5);basketModule.addItem(item:butter,price:0.3);console.log(basketModule.getItemCount();console.log(basketModule
18、.getTotal();/however,the following will not work:console.log(basketModule.basket);/(undefined as not inside the returned object)console.log(basket);/(only exists within the scope of the closure)那在各个流行的类库(如 Dojo,jQuery)里是如何来做呢?Dojo Dojo 试图使用 dojo.declare 来提供 class 风格的声明方式,我们可以利用它来实现 Module 模式,例如如果你想再
19、 store 命名空间下声明 basket 对象,那么可以这么做:/traditional way var store=window.store|;store.basket=store.basket|;/using dojo.setObject dojo.setObject(store.basket.object,(function()var basket=;function privateMethod()console.log(basket);return publicMethod:function()privateMethod();();结合 dojo.provide 一起来使用,非常强大
20、。YUI 下面的代码是 YUI 原始的实现方式:YAHOO.store.basket=function()/private variables:var myPrivateVar=I can be accessed only within YAHOO.store.basket.;/private method:var myPrivateMethod=function()YAHOO.log(I can be accessed only from within YAHOO.store.basket);return myPublicProperty:Im a public property.,myPu
21、blicMethod:function()YAHOO.log(Im a public method.);/Within basket,I can access private vars and methods:YAHOO.log(myPrivateVar);YAHOO.log(myPrivateMethod();/The native scope of myPublicMethod is store so we can /access public members using this:YAHOO.log(this.myPublicProperty);();jQuery jQuery 里有很多
22、 Module 模式的实现,我们来看一个不同的例子,一个 library 函数声明了一个新的 library,然后创建该 library 的时候,在 document.ready 里自动执行 init 方法。function library(module)$(function()if(module.init)module.init(););return module;var myLibrary=library(function()return init:function()/*implementation*/;();对象自面量 对象自面量使用大括号声明,并且使用的时候不需要使用 new 关键字
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大型 JavaScript 应用程序 架构 模式
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内