大型Javascript应用架构的模式(译文)
附上翻譯好的word文件?http://files.cnblogs.com/lizhug/Patterns_For_Large-Scale_JavaScript_Application_Architecture.zip
?
作者:Addy Osmani?? 技術評審:Andree Hansson??? 翻譯:李珠剛 @珠剛參上
?
今天我們將要探討一系列用于大型Javascript應用架構的實用的模式。這個題材來源于我上次在LondonJs的同名演講以及Nicholas Zakas先前的工作的一些啟發。
?
我是誰?我為什么要說這個話題?
我現在是就職于AOL公司的Javascript和 UI工程師,主要設計和編寫我們下一代面向客戶的應用程序的前端架構。由于這些應用程序不僅復雜而且經常需要一個具有可擴展性和可復用的架構,確保應用于這些應用程序的模式盡可能的可持續是我的工作職責之一。
?
我把自己看作一個設計模式的狂熱者(雖然對于這個話題有很多遠比我知識豐富的專家)。我之前寫了creative-common書本<essentail Javascript設計模式>,在寫篇文章的的過程中我將同時引用那本書的一些細節。
?
你能在140字之內概括這篇文章么?
如果你的時間很緊,這里就有一個概括
?
去耦應用. 架構 w/模塊,外觀和中介者模式
?
?
什么是’大型’Javascript應用
在我們開始之前,讓我們嘗試去定義一下Javascript應用程序中我們所理解的’大型’是什么。
我對于這個問題的答案是很主觀的而且可能會與其他有多年經驗的工程師有很大不同。
?
我詢問了一些中級工程師他們對于’大型’的理解。一個工程師是這樣說的:”超過十萬行代碼的Javascript程序” 同時另外一個說:”程序內部的Javascript代碼有1M以上的程序”. 如果這些想法不是瘋了的話,這兩個說法應該都是錯誤的。
?
我自己的定義可能不會被大眾接受,但是我相信這個定義可能接近了’大型’這個意思
?
在我看來,大型可擴展的Javascript應用程序是需要的工程師努力去實現的非凡的應用程序,需要處理大量的數據同時傳遞給瀏覽器。
?
定義的最后一句話是最意味深長的。
?
讓我們回憶一下你現在掌握的架構
?
如果正在為一個有意義的大型Javascript應用程序工作,記得留出充分的時間去計劃潛在的將會有很大意義的架構。它通常比你剛開始想象的更加復雜
?
我非常想要強調這一點的重要性-------我看到的一些靠近大型應用程序的工程師已經往回走了而且說:”好吧,這里有一系列的對于我上次一個中型的可擴展的項目有良好幫助的想法和模式,他們理所當然可以應用于再大一點的應用程序,不對么?” 盡管這在一定程序上是正確的,但是請不要想當然-------更大的應用通常有更多的需要考慮的因素。我將簡短討論一下為什么要花時間設計你的應用程序結構從長遠來看是值得的。
?
大量的Javascript工程師可能在他們現在的架構中使用混合方式組合下列的一些結構
1、自定義部件 custom widget
2、模型 model
3、視圖 views
4、控制器? controllers
5、模板? templates
6、庫/工具包??? libraries/toolkits
7、應用程序核心?? an application core
?
相關閱讀
Rebecca Murphey - Structuring JavaScript Applications
Peter Michaux - MVC Architecture For JavaScript Applications
StackOverflow - A discussion on modern MVC frameworks
Doug Neiner - Stateful Plugins and the Widget Factory
?
你可能也會分解你的應用程序函數,使他們成為一個個的模塊,或者應用其他的模式。
這是值得鼓勵的,但是如果這是你應用的全部架構的話,這里也會有一些你可能遇到的潛在問題。
?
1、你的架構有多少可以被立即重新實用的?
單一的一個模塊可以獨立存在么?他們是自包含的么?如果我現在看你們團隊正在工作的大型應用的代碼庫然后隨機選擇一個模塊,他可以嵌入一個新的頁面然后開始使用么?你可能在做之前會對這個方法產生質疑,然而我還是鼓勵你去考慮一下未來。如果你的公司開始去構架越來越多出色的應用哪些函數能夠復用呢?如果有人說:”我們的用戶喜歡在郵件客戶端使用聊天模塊,讓我們把這個模塊嵌入我們新的編輯套件里面吧” 那么有沒有可能不經過深入修改就能使用這個模塊呢?
?
2、在你的系統里有多少模塊是需要依賴其他模塊的呢?
他們是緊密耦合的么?在我探討這個概念之前我需要申明 我理解在一個系統中模塊之前絕對的不相互依賴是不大可能做到的。在粒度級別上你可能有模塊需要依賴其他模塊的功能,但是這個問題在功能模塊群之間是更加有直接關系的。這些一系列在你的應用里直接相關不依賴太多其他模塊或者函數是否運行或者被裝載好是可能的。
?
3、如果你的應用里的特殊部分癱瘓了,應用還能運行么?
如果你正在構建一個類似Gmail的應用,你的網絡郵件模塊奔潰了,這不應該造成阻塞UI或者阻止用戶使用應用的其它功能 比如聊天功能。同時,按照之前的,模塊在理論上應該能夠自動退出這個應用架構。在我的講話里我提到了基于表達用戶意圖的動態模塊。例如,在Gmail的例子里當核心模塊初始化的時候聊天模塊并不會被啟動。以后當用戶傳遞一個信息去使用聊天模塊,他才會被動態裝載。理論上來說,你希望他不會對應用的其他部分造成負面影響。
?
4、單獨檢測你的一個模塊有多容易?
當測試一個具有良好擴展性的系統,這個系統可能需要滿足潛在的上千萬的用戶去使用不同的模塊,模塊被重用于不同的應用是非常有必要的。當模塊被初始化的時候,不管在架構的內部或者外部都需要滿足測試的要求。在我看來,這有這樣這個模塊用于其他系統也不會出問題的觀點才有說服力。
?
目光長遠
當你設計大型應用程序的架構的時候,往前多想一步是很有必要的。不僅僅是一個月或者一年后,我們要考慮更加長遠。什么會改變呢?去猜想你的應用會變成什么樣當然是不可行的,但是這里有幾個方面值得考慮的。在這里,在你的應用里至少有一個特殊的層面會出現在你的大腦里。
?
工程師經常把他們的DOM操作的代碼跟應用的其他部分很緊密的耦合在一起,甚至當他們不辭勞苦的去把他們的核心邏輯分拆成模塊的時候也會這樣做。你看看….從遠來看這難道不是一個好建議么?
?
有讀者可能會說,現在所定義的嚴格地架構并不一定適用于以后。這個觀點是正確的,但是如果沒有更多的因素考慮在內的話,有另外一種概念可能更加有用
?
出于表現性、安全性或者未來的設計性,我們可以從Dojo, jQuery,Zepto 或者 YUI之中選擇一些完全不同的東西。這會造成一個問題,因為庫不是可以那么簡易的互相交換的。如果這個庫在你的應用中被應用的很普遍,那么庫的替換將會造成很大的性能問題。
?
如果你是一個Dojo工程師(就像我講話里的一些讀者),你可能沒有更好的想法去改變你所應用的庫,但是誰能說2-3年后不會有你想要的更好的庫出來呢?
?
在一個小的代碼庫里面這可能一個相對來說不是太重要的抉擇,但是對于大的應用,有一個能夠靈活的不用太介意在你的模塊里用了什么樣的庫,從經濟以及節約時間的角度來看,將會產生極大的益處。
?
總的來說,如果你現在回顧一下你的架構,在不完全重寫你的應用的基礎上你能夠切換你使用的庫么?如果不能,那就要考慮繼續閱讀這篇文章,因為我覺得今天列出的一些架構將會很有趣。
?
有一些很有影響力的Javascript工程師已經說了一些我今天提到的一些概念。這邊有三個觀點我提供分享。
?
“構建大型應用程序的秘訣就是永遠不要去構建大型應用程序,把你的應用拆分成小的塊,然后把那些通過測試的,小的塊集成到你的應用里面去”----Justin Meyer, author JavascriptMav
?
“秘訣就是你要承認在剛開始的時候你對于這個程序會發展成什么樣沒有任何想法。當你接受了你什么都不知道,你開始去防御性的去設計這個系統,你能識別出可能改變的簡單的需要你花費一些時間的關鍵點。舉個例子,你應該希望應用里面與其他系統交互的任何部分都能改變,所以你需要把他們抽象化”---Nicholas Zakas, author ‘High-performance Javascript Website’
?
最后一個但同等重要的
?
“把組件互相綁得越緊,復用性就會越低,而且當沒有改變影響他的其他組建的時候更改組建將會很麻煩”? ----Rebecca Murphey,author of jQuery Fundamentals
?
這些原則在構建可以經受時間考驗的架構的時候是很重要的,并且需要一直在你的腦海里。
?
頭腦風暴
讓我們想想我們一會兒將要去實現什么。
?
我想要有一個把函數裝進不互相依賴的獨立的模塊的松耦合的架構。 當發生了一些有趣的事,這些模塊將會向應用的其他模塊傳遞信息,中間層將會解釋以及對這個信息進行解釋
?
舉個例子,假設我們擁有一個用于在線面包店的應用,有一條從模塊中發出”有趣的”信息可能是”有一批42個面包卷準備好被發配”
?
我們使用不同的層從模塊里去解釋這些消息
a) 模塊不會直接獲取這些要點
b) 模塊不需要直接調用或者互相影響,這一點保證了當特殊模塊產生錯誤的時候該模塊不會崩潰同時提供給我們重新啟動已經奔潰的模塊的方式
?
另外一個概念就是安全性。事實是我們當中很多的人都不把應用內部的安全當作一個概念。我告訴自己當我們搭建應用的時候,我們有足夠的能力去分辨公有和私有的部分。
?
然而,如果你有辦法來確定哪些模塊是系統中允許的,他是不是不會提供幫助?比如,假設我知道我在系統中沒有權限用公共聊天組件與一個管理員模塊或者數據庫寫的模塊連接,通過一些XSS,我可以限制有人利用我已經在組件中發現的漏洞的機會。模塊不應該去使用任何東西。他們可能可以 在大多數現在的架構中,但是他們真的需要么?
?
擁有一個中間層操控什么模塊可以操作你的框架的哪個部分將會增加你系統的安全性。這意味著模塊只能做他們被允許做的事情。
?
?
?
可行的架構
我們想要去定義的一個架構集合了下面三個著名的設計模式:模塊,外觀,中介者。
?
相比較于模塊之間直接互相溝通的模型,在這個解耦的架構中,他們將用有趣的東西(理想的說,不知道系統的其他模塊)替代發布事件。 中介者模式將被用來想這些模塊發布信息,也將操控什么樣的返回信息適合作為響應。 外觀模式將會被用來模塊之間的授權。
?
我下面將介紹這些模式的細節(注:其實就是下面將要講的目錄)
?
1 設計模式
???????? 模塊理論
?????????????????? 高度的概括性
?????????????????? 模塊模式
?????????????????? 對象字面量
?????????????????? CommonJs模塊
???????? 外觀模式
???????? 中介者模式
2 應用到你的架構中
???????? 外觀模式 – 抽象的核心
???????? 中介者模式 – 應用的核心
???????? 把他們混合起來
?
?
模塊理論
你可能已經在你現有的架構中應用了一些模塊了。但是如果你沒有的話,這邊將給你一個將蛋的介紹
?
在一個健壯應用架構里面、模塊是一個完整的小塊而且在一個大的了可相互交換的系統中只有一個典型的目的。
?
取決于你怎么實現你的模塊,定義可被一起立即自動裝載的模塊之間的依賴性是可行的。相比起必須去追蹤他們之間的大量依賴以及手動裝入模塊或者引入腳本標簽,這個方式是更加有擴展性的。
?
?
任何非凡的應用都應該從模塊化的接口基礎上建立。 再回到Gmail這個例子中,你應該把模塊看成一個獨立存在的功能單元,例子中的聊天模塊就是其中之一。他可能有聊天模塊,然而,他有多少個子單元,取決于你的功能單元有多復雜。舉個例子,有一個簡單的功能可能去操控那些表情可以在聊天和郵件接口中共用。
?
在架構的討論中 ,模塊對于系統中其他模塊的了解是非常少的。所以,我們通過外觀模式把這個職責給中介者。
這是靠設計的因為如果一個模塊只負責讓系統知道什么時候不需要擔心其他模塊是否在運行的有趣的事情發生了,一個系統應該滿足在緊耦合的設計中支持在不讓其他模塊停止的情況下,增加、刪除或者替換該模塊。
?
因此如果這個想法實現的話,松耦合是很重要的。它促進了模塊通過移除代碼可以實現更簡易的維護。在我們的例子中,為了讓功能變的正確,模塊不應該依賴其他模塊。當松耦合被很好的利用其來了的話,改變系統的一個部分將會如何影響其他部分是很容易可以預見的。
?
在Javascript中,在實現模塊的時候有許多不同的實現模式,這里就包括比較有名的 模塊模式和字面量。有經驗的工程師已經對這個熟悉了,如果是這樣的話,那就直接去看commonJs模塊吧
?
模塊模式
?
模塊模式是一個可以很好的把隱私模塊,狀態,結構用閉包封裝起來的設計模式。它提供了方法把公有的和私有的方法變量包裝起來,防治部分代碼段進入全局作用域造成跟其他工程師的接口沖突。用了這個模式,只有一個公有的API會返回,其他的都會被封裝在閉包之內。
?
對于保護邏輯去處理繁重的數據處理提供了一個很簡潔的方案同時只要暴露了一個接口給程序的其他部分去使用。這個模式跟立即函數(IIFE)的表達很像,除了返回的是一個對象而不是一個函數。
?
有一點需要注意,javascript中并沒有真正的私有的概念,因為跟傳統的語言不同,他并沒有訪問修飾符。變量既不能被顯示的定義成私有或者共有,所以我們使用函數作用域去模擬這個概念。在模塊模式里面,因為有了閉包,變量或者方法可以只能在函數中被獲取。然后在返回的對象的中的變量或者方法任何人都可以獲得。
?
下面你可以看到一個使用模塊模式實現了的購物籃的例子。這個模塊在全局對象中本身是完全自包含的,叫做basketModule。模塊里的Basket數組保證了私有性所以你的應用的其他部分不能直接去讀取他們。它保證了只能通過你所定義的作用域中的函數才能獲取basket的值。
?
?
?
在這個模塊里面,你會注意到我們返回了一個對象。他被basketModule自動獲取,所以你才能像下面這樣調用
?
?
?
?
上面的方法很好地在basketModule中構建了一個命名空間
?
從歷史的角度來看,模塊模式是有很多人包括Richard Cornford在2003年建立起來的,
隨后它被Douglas Crockford在他的演講中被普及話,然后 Eric Miraglia在YUI的博客中被重新介紹了一下。
?
?
模塊模式是怎樣在特殊的工具包或者框架中表現的呢?
?
Dojo
?
Dojo通過dojo.declare提供可以通過實現模塊模式的用于其他東西中的跟類類似的功能。舉個例子,如果我們想要定義store命名空間中的basket這個模塊,它可以這樣實現
?
?
混入dojo.provide的話這個會變的很強大
?
YUI
?
下面這個例子很大程度上基于Eric Miraglia實現的原始的YUI 模塊模式、相對來說還是很容易理解的
?
?
?
jQuery
?
把jquery的代碼被包含在模塊模式中有很多種方式。如果模塊之間有一些公用的部分,Ben Cherry 建議在模塊中使用函數包裝器。
?
下面的例子,一個定義新庫和自動初始化的庫函數在document.ready中被定義了
?
?
?
相關閱讀
Ben Cherry - The Module Pattern In-Depth
John Hann - The Future Is Modules, Not Frameworks
Nathan Smith - A Module pattern aliased window and document gist
David Litmark - An Introduction To The Revealing Module Pattern
?
?
對象字面量
?
在對象的字面量中,一個對象被描述成一系列的用逗號分隔、用 {} 包含的鍵值對,
?
對象中的鍵可以是字符串也可以是跟隨在冒號后面的標識符。在最后一個鍵值對后面不應該有逗號出現不然會出現錯誤
?
對象字面化不要求使用new實例化,但是不允許在申明的時候就使用括號里面的東西。下面你將會看到一個使用字面量語法的例子。新的成員可能被加進對象里面就像myModule.property = 'someValue';
?
盡管模塊模式對于很多東西都是很有用的,但是如果你發現你自己不需要特殊的值或者方法需要變成私有的,對象字面化將會更加適合你
?
?
?
相關閱讀
Rebecca Murphey - Using Objects To Organize Your Code
Stoyan Stefanov - 3 Ways To Define A JavaScript Class?
Ben Alman - Clarifications On Object Literals (There's no such thing as a JSON Object)
John Resig - Simple JavaScript Inheritance
?
?
CommonJS模式
在過去兩年里,你可能聽說過了commonJS 一個設計規范和標準化javascript API的志愿組織。迄今為止他們已經批準了模塊和包的標準。CommonJS AMD提議指定了把script同步和異步加載如瀏覽器的簡單的API。他們的模塊模式相對來說是干凈的而且我覺得這是JS邁向下一個時代的臺階。
?
從結構化的角度,CommonJS的模塊是一個可重用的一段JavaScript給特定對象提供任何相關的代碼。這個模塊的標準越來越普遍的變成標準模塊標準。有一些非常出色的教程來教授實現CommonJS模塊 但是總的來說,他們基本包含兩個基本的部分:一個需要引入其他對象的exports對象、一個引用其他模塊的reqiure函數。
?
?
?
?
有許多出色的javascript庫可以像commonJS一樣引入其他js,我個人使用的就是RequireJS。完整的requireJS我就不能在這個教程中介紹了,但是我推薦閱讀James Burke的東西,我知道一些人也像Yabble(沒有這個單詞呀)
?
除了這個, RequireJS提供了我們怎么樣去延遲創建有包裝器以及可以異步加載的工藝模塊的靜態模塊。他可以簡單的引入模塊,他們依賴于他們的方式,如果有模塊的話他們就會運行。
?
有許多工程師批評commonJS模塊對于瀏覽器不夠適合。理由是他們如果沒有服務端的幫助的話并不能通過script引入。我們能想象一個用ascii去編碼照片的的庫可能會引入一個encodeToASCII函數,一個模塊可能類似這樣。
?
?
?
這種類型的方案用script標簽將不會工作,因為作用域沒有被包含,就是說encodeToASCII方法沒有被綁定到window對象中,require將不會這樣定義,對于每個模塊exprots將需要分別地被創建。一個需要服務器端支持的客戶端的庫或者一個需要利用eval() 的XHR請求的script能很簡易的操作。
?
使用RequireJS,模塊可以被更加簡易的重寫。
?
?
對于不需要在項目里面依賴使用靜態Javascript的工程師,CommonJS的模塊是是一條出色的路,但是確實需要花費一些時間去研究它。我現在才涉及到冰山一角,但是CommonJS和Sitepen有一系列的資源去學習
?
相關閱讀
The CommonJS Module Specifications
Alex Young - Demystifying CommonJS Modules
Notes on CommonJS modules with RequireJS
?
外觀模式
?
接下來,我們將來看一下外觀模式,一個在如今的架構中出于關鍵地位的模式
?
當你提到外觀,你經常創建一個隱藏真實性的外表。外觀模式為了對于提供了一個便捷的高層接口,隱藏了底層的復雜性。可以把他現象成為其他工程師提供的簡化接口。
?
外觀是經??梢栽趈avascript庫和框架中看見的結構化的模式,雖然他可能支持大量的行為的方法,但是一個’外觀’抽象成了一個讓客戶端去使用。
?
這個方面了我們去跟外觀交互而不是去跟后臺的子程序交互。
?
外觀很棒的理由就是他隱藏了在一個獨立模塊中功能本身特殊實現的細節。模塊的實現可以在客戶端不知道的情況下改變。
?
依靠維持一個一致的外觀,模塊內部是不是使用了dojo,jquery,YUI,zepto或者其他東西是不重要的。只要接口沒有改變,在不影響系統其他部分的前提下,你保持了去切換庫的能力
?
下面是一個關于外觀的非常基礎的例子。就像你看到的,我們的模塊包含了一系列的私有的方法,外觀提供了大量的簡單API去使用這些方法。
?
?
?
這個就是我們把外觀應用到我們的架構前的樣子。接下來我們投入到令人振奮的中介者模式。
中介者模式和外觀模式最核心的不同點是 外觀(結構化的模式)僅僅暴露已經存在的功能然而中介者模式(行為化的模式)能夠動態的添加功能
?
相關閱讀
Dustin Diaz, Ross Harmes - Pro JavaScript Design Patterns (Chapter 10, available to read on Google Books)
?
中介者模式mediator pattern
?
用一個類比來介紹中介者模式可能更加好------你想想看我們典型的飛機場的操控,控制塔控制什么飛機能夠起飛什么飛機能夠下降,因為所以的信息交流都是從飛機和控制塔之間的,而不是飛機之間互相傳遞起飛降落的這些信息----(個人注:這個例子很好)有一個中心的控制對于這個系統的成功運行有良好的意義,而這個就是中介者模式所做的。
?
當模塊之間的交流變的很復雜的時候中介者模式就很有用了,但仍然是意義明確的。如果在你系統的代碼模塊之間表現出很多的相關性,那么現在就該設置一個控制中心了。
?
在現實生活中,中介者把不同模塊的交互通過媒介壓縮在了一起。這個模式通過防治對象之間的相互依賴達到了良好的松耦合性-----在系統中,這幫助我們解決了模塊依賴性問題。
?
他還提供了什么優點呢?中介者允許模塊操作去改變獨立性,所以這個是非常靈活的。如果你之前已經用過了觀察者模式(PUB/SUB)模式去實現兩個模塊之間的廣播,你會發現中介者模式是如此的容易理解。
?
讓我們看看從高層看中介者中模塊是如何交互的
?
?
?
把模塊當作發布者,把中介者當作發布者和訂閱者。模塊1 廣播了一個事件提醒中介者需要去做,中介者捕獲這條信息然后開啟需要去處理這條信息的模塊2、告訴他模塊1需要你,然后處理完車過后模塊2發送一條廣播信息給中介者,同時模塊3被中介者啟動去記錄同志的結果。
?
注意,如何在模塊之間沒有直接交流的點。如果在這條鏈中的模塊3失敗了或者錯誤停止了,中介者可以假設暫停了其他模塊上的任務,停止和重啟模塊3,然后在對系統影響很小的情況下繼續工作。這種程度的解耦的一個主要優勢是提供的模式。
?
回顧一下中介者的優點:
?
他通過有一個中心的控制點防止了模塊的相互直接依賴。這個只會造成一個很小的性能下降。
-----因為松耦合的自然性,只通過觀察廣播中的信息是無法知道系統是如何響應的。最后,緊耦合是令人頭疼的主要原因、下面就是一個解法;
?
例子:這是一個可行的中介者模式的實現 by @rpflorence
?
?
?
?
?
這是上面的兩個具體應用,他很好的控制了發布者和訂閱者
?
?
相關閱讀
Stoyan Stefanov - Page 168, JavaScript Patterns
HB Stone - JavaScript Design Patterns: Mediator
Vince Huston - The Mediator Pattern (not specific to JavaScript, but a concise)
?
外觀模式的應用:抽象的核心
在架構中的建議
外觀作為一個把應用核心抽象的角色,充當了中介者和我們的模塊之間的角色。它是唯一的系統的其他模塊能夠了解的一個部分。
?
這個抽像者的職責包括,保證提供給這些模塊的接口是穩定的。他比較類似于Nicholas Zakas首先提出來的沙箱中的控制者
?
組件通過外觀與中介者進行交互,因此他需要變得很可靠。當我說到”交流”,我需要解釋的一點是 外觀就像是中介者的一個抽象表示,他將會去監聽從模塊中傳遞過來的信息然后傳遞給中介者。
?
除了提供接口給模塊外,外觀也表現為一個警衛,決定了應用的那個模塊可以從他這里獲取數據。組件僅僅只能調用他們自身的方法而不可以做他們不被允許做的事情。舉個例子,一個模塊或許會發出這樣的信息dataValidationCompletedWriteToDB? 安全檢查的保證就是模塊已經被授權了請求數據庫寫入。我們理論上希望做到避免模塊意外的去做了他們不被許可的事情。
?
簡短的回顧,中介者保留了觀察者模式的控制方式,但是他們只做外觀同意他們做的事情。
?
中介者模式的應用:應用的核心
?
中介者充當了應用核心的角色,我們已經簡短的了解了一些他的職責,現在我們把他們的職責都介紹一下。
?
這個核心最基本的任務時控制模塊的生命周期。當核心檢測到一個消息,它將決定什么模塊將被啟動 --- 他意味著決定了那個模塊或者哪個系列的模塊需要被啟動或者停止。
?
一旦一個模塊被開啟,他理論上需要自動啟動。關于什么時候DOM已經就緒或者對于模塊來說是否足夠的作用域這不是核心所需要關心的事
?
你可能對一個模塊什么情況下該被停止感到奇怪。如果一個應用探測到一個特殊的模塊已經失效或者傳遞出了錯誤的信息,核心就會做出一個決定防治這個模塊繼續運行下去,而是去重啟他。這里的目標是去幫助降低用戶的破壞性。
?
除此之外,核心應該可以在不影響其他部分的情況下移除或者獲取模塊。一個典型的例子是某個模塊中的一個功能可能在初始的頁面中不需要了。但是根據用戶的操作去動態的加載。
讓我們返回到Gmail這個例子中,google可以使聊天模塊動態加載當用戶需要使用這個功能的時候。從表現最優的角度來看,這個一個非常有意義的做法。
?
錯誤的管理也將由應用核心來操作。除了廣播模塊之間的消息,他們也會廣播任何錯誤的信息,然后根據具體的錯誤信息去處理。在解耦的架構中這去擁有足夠的范圍去操作新的或者更好的方法或者報錯是非常重要的。使用通過中介者使用觀察者的方法允許了我們去做這個。
?
把他們都一起來講一遍
1、模塊包含了你應用里的特殊的功能塊。他們通知系統什么時候有一個他們感興趣的事件發生了。我將會在下面的問答中解釋,模塊依賴于DOM工具方法,但是理論上不能依賴系統中的其他模塊,他們不應該被這樣理解:
???????? ① 哪些對象或者模型訂閱了他們發布的信息
???????? ② 這些對象基于什么(服務器端或者客戶端)
???????? ③ 多少對象訂閱了通知
?
?
?
2、外觀抽象了核心是為了防止模塊直接去跟他交互。他訂閱了他感興趣的事件并且說”非常好!發生什么事了?”他同樣通過檢測模塊是否擁有必要的權限控制著模塊的安全性。
?
?
?
3、中介者(應用的核心)通過中介者模式充當了一個”發布/訂閱”管理者的角色。它主要負責模塊的管理、啟動停止模塊。在動態加載中以及保證模塊能夠被重啟中被特別的應用了。
?
?
?
?
超越發布/訂閱:自動的事件注冊
?
就像 Michael Mahemoff 先前提到的,當考慮大型的可擴展性的Javascript的時候,開發語言中有類似動態語言特征是很有好處的。你可以在Michael Mahemoff的G+博客中獲得更多的關于這一方面的概念,但我推薦你去看一點 ----動態事件注冊(AER)
?
AER通過名傳遞,實現了發布者和訂閱者的自動連接。舉個例子,如果一個模塊發出了一個事件叫做messageUpdate 任何有messageUpdate 這個方法的都將被調用。
?
這個模式的建立涉及了所有訂閱了這個方法的接口,注冊了所有的訂閱的事件,以及所有接口集中的子事件,并把事件跟他綁定起來。這是一個構架中的非常好的途徑,但是可能會遇到一些挑戰。
?
舉個例子,當動態運行的時候,對象可能需要在運行之前就綁定完畢。請去看一下Michael公布的怎樣去深層的操作這些東西。
?
常見的問題和解答
Q:是不是可以避免實現沙箱或者外觀
A:雖然在架構的概述中使用了外觀去實現安全的要求,但是他們完全可以只用一個中介者以及發布和訂閱去實現事件在應用之中傳遞。所有的版本都提供一個類似的解耦,但是請保證你在操作模塊之間直接操作的時候是很得心應手的。
?
Q:你提到了模塊沒有任何依賴,這是不是意味著它不依賴第三方的庫?(比如jQuery)
A:我將再提一遍依賴于其他模塊的這個概念。一些工程師選擇一個類似架構的時候通常選擇他的DOM的抽象工具庫。例如一個人可能使用jquery查詢的DOM并且返回結果的庫(也可以是Dojo或者其他)用這個方法,雖然所有的模塊都查詢了DOM,但是他們沒有直接使用庫或者工具包里面硬編碼的函數。關于怎么去實現它有很多不同的方法,但是理論上構架的時候核心的模塊不應該依賴于其他模塊。
?
你將會發現在這個例子中 有些時候從其他工程中拿一個模塊放到另外一個工程中是很容易的。我應該申明一點我完全同意有些時候把模塊里面的一部分功能移到或者擴展到另外一個模塊可能是有點困難的,但是你需要有這個概念,就是他將會在其他模塊中很好的適應。
?
Q:我今天開始就將使用架構。有沒有什么樣板代碼讓我去學習的?
A:如果時間允許我將發出這部分的代碼,但是同時,Android Burgee(完全的開源,我再介紹給別人的時候也再一次的去回顧了一下)的”writing Modular Javascript”或許是一個很好的選擇。Andrew的包 包括了包括了截圖代碼以及今天介紹內容里面的絕大部分內容。就像我回答的第二個問題,andrew選擇了一些有趣的模式去查詢DOM,選擇庫就可以只修改一點點的代碼。我并不絕對的認為這就是正確的或者最好的方法,但是我個人也在使用的一個手段。
?
Q:如果一個模塊需要直接跟核心通信,可以么?
A:就像 Zakas 已經提到的,在技術上是沒有理由說為什么模塊不能跟核心直接聯系的、但是這是一個很好的規則而已。如果你想要嚴格的堅持這個架構,你需要遵循這個規則或者選擇一個松耦合的架構。
?
?
鳴謝
感謝Nicholas zakas他的工作帶來的一系列想法。也感謝Andree Hansson提供了技術審核。
Rebecca Murphey, Justin Meyer, John Hann, Peter Michaux, Paul Irish and Alex Sexton,已經討論過跟這個主題類似的話題,這是我和其他人靈感的源泉。
?
轉載于:https://www.cnblogs.com/lizhug/archive/2013/04/30/3051681.html
總結
以上是生活随笔為你收集整理的大型Javascript应用架构的模式(译文)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: table数据表 边框特效
- 下一篇: 读写Excel2003文档