只是一點淺見啊 摺疊也活該。。。javascript
M-V- X 本質都是同樣的 重點仍是在於M-V 的橋樑css
要靠 X來牽線。html
X的模式之間不一樣 主要是 M與V 的數據傳遞的流程不一樣。前端
數據傳遞的流程不一樣來源於運行環境技術棧可以作到的事情不一樣。java
因此不管是複雜化 簡單化 仍是修改流程,基本都是由於技術棧變化了 對應作的調整。node
在相同技術棧下 可以實現的各類 X均可以是大同小異的。 算法
在不一樣技術棧下 相同的X可能實現都截然不同,僅有很是抽象的流程相似。編程
我是大天然的搬運工。瀏覽器
這是我在博客園正好寫的一篇Blog,但願對你有用:從Script到Code Blocks、Code Behind到MVC、MVP、MVVM
=====================(Hi,我是分割線)=====================
剛過去的週五(3-14)例行地主持了技術會議,主題正好是《UI層的設計模式——從Script、Code Behind到MVC、MVP、MVVM》,是前一天晚上才定的,中午花了半小時準備了下就開講了。
今天看到了你們在爲MVVM knockout.js友(ji)好(lie)地交流,因此就整理下而後更擴展地分享。
主要目的也不是爲了爭論,畢竟只是正巧主題相近,本來的打算也就是一次技術分享而且記錄下來。
那麼咱們就按照大體的歷史進程將這些概念進行劃分:
咱們知道的是現實的歷史發生順序並不如上,由於思想都是類似的,好比MVC很早很早就出現了,解釋型語言至今基本上也有不少分支並且在互聯網時代大行其道。
但我要說的是:不要在乎這些細節!
固然了,這是玩笑,個人意思是,這些內容我懶得應該在另外獨立的主題探討,篇幅也有限。
這裏腳本的意思不是指當時是用腳本開發,而是像寫腳本同樣開發。它們都有一個特色:功能單1、管理單1、入口單一。
咱們最先的程序是彙編,當時的碼農的工做是兼職,工做內容是編寫一套壽命不長的機器控制指令,有些甚至是命令,好比至今依然保留的Command(亮點自尋):
到後來計算機被用於科學計算等,需求推進了須要更高的開發效率,因此咱們有了高級語言。
那個時候碼農其實可能是數學家,程序的做用很簡單,就是執行一些數學計算,相似今天ICPC的一些算法問題,好比Hello World:
main()
{
printf("hello,world\n");
}
這時候,程序還能夠被歸結爲輸入到輸出的過程,咱們還能去講講馮諾依曼模型。
在這個時代,開發是指編寫機器指令,甚至都不配用「開發」這個詞來描述這項工做。
軟件、UI和Markup Language在那個時代講UI等於放屁,根本不存在這種概念。但全賴咱們有神器——摩爾定律。
但我我的認爲摩爾定律是不足以讓一個敲命令行的時代在幾十年間轉變成這種各種框架技術架構實踐模式的時代,真正推進計算機造成自有的工程學體系的是還有兩樣東西就是:
由於人的能力並無「跟上」機器,因此纔會出現各類模式、方法、工具等等來補足人的不足,以最大地透支機器性能。就像我前幾天在閃存無聊時忽然想到的一句: 架構是對客觀不足的妥協,規範是對主觀不足的妥協。
當咱們須要機器作的事情多了起來,咱們就沒辦法在一個芯片上解決全部事情,因此纔會有馮諾依曼模型、計算機架構,沒辦法用一臺機器解決,因此纔要互聯網、分佈式、雲計算。
一樣,隨着計算機的發展,要作的事情多了,就出現了軟件的概念。當「開發」正式化,咱們需求的軟件就變得:功能繁雜、管理統1、多入口。
真正變化的不是客觀本質,而是需求。就像這裏說的「軟件入口」在客觀上咱們仍是隻有一個,原理上始終都只有一個啓動程序、一個啓動代碼片斷。但「軟件的入口」,已經從指代Main函數變成了指代起始UI,用戶已經從指代專業人士變成了指代通常消費者,先有軟件的需求,纔有軟件的定義,而需求是在變化的。
一個軟件須要比當時多幾個數量級的代碼:
因此咱們須要添加索引、用多個文件組織代碼。
機器的發展和軟件的需求擴大和細化,咱們開始出現了用戶界面(User Interface)的概念和最適合用於界面的語言——標記語言(Markup Language)。固然,ML不是爲UI而生的,它只是十分適合UI,因此才和UI墜入愛河。
由於有了更高UI的需求,因此代碼才正式被分化爲描述作什麼(業務邏輯)和有什麼(UI)的兩部分,由於咱們開發時沒辦法在兩種思惟方式下同時工做,開發時的人腦是單線程的。咱們所看到的同時進行UI和邏輯開發只不過是咱們學會了在兩種模式下快速切換,看起來像同時進行,而不是真正的同時進行。一樣的狀況也發生在不一樣的代碼片斷的開發中。
分化的狀況除了UI,還發生在方方面面,好比數據操做、UI的對象和樣式分離,咱們仍是繼續從UI講下去吧。
UI和邏輯分開了兩種語言來寫,可是它們也要放在同一個項目中,由於它們本來就是要一塊兒工做的。即便是分開,也須要相連,由於這是它們原本要解決的問題。
這時候咱們出現的(一般的)解決方案就是Code Block和Code Behind。雖然從時間上彷佛Code Block比Code Behind要早,有種感受就是越新越好,但實質上它們正交替地發展着,由於誰也沒辦法解決UI和邏輯代碼分化後的一個哲學問題——UI和邏輯是一塊兒的,可是它們卻不是一塊兒的。
Code Block能很好地處理UI和邏輯間在一塊兒的關係,你在同一個地方能夠同時維護UI和邏輯:
1 @model GM.OA.Finance2.Web.Models.FinancialBase.CurrencyModel
2 @{
3 ViewBag.Title = "EditCurrencyDrawer";
4 Layout = "~/Views/Shared/_DrawerLayout.cshtml";
5 }
6
7 @section styles {
8 <link href="/Content/base/table-form.css" rel="stylesheet" />
9 <link href="/Content/base/drawer.bigtitle.css" rel="stylesheet" />
10 }
<a href="#" class="addcurrency oa-btn" oa-style="green">添加新幣別</a>
<script type="text/javascript">
$(document).ready(function () {
$('.addcurrency').click(function () {
$.oa.drawer.openUrl('AddCurrencyDrawer/', 'addcurrency', {
width: 300
});
});
});
</script>
Code Behind能很好地處理UI和邏輯各自分開的關係,你可讓UI和邏輯各自作好各自的事情:
<asp:Button ID="RemoveSelectedCurrency_Button" runat="server" Text="刪除選中幣別" OnClick="RemoveSelectedCurrency_Button_Click" />
<asp:Button ID="RemoveAllCurrencies_Button" runat="server" Text="刪除全部幣別" OnClick="RemoveAllCurrencies_Button_Click" />
1 protected void RemoveSelectedCurrency_Button_Click(object sender, EventArgs e)
2 {
3 var currencyId = Currencies_ListBox.SelectedItem.Value;
4 currencyManager.Remove(currencyId);
5 }
6
7 protected void RemoveAllCurrencies_Button_Click(object sender, EventArgs e)
8 {
9 currencyManager.RemoveAll();
10 }
由於存在兩種實現方式,因此就存在了對比,由於存在了對比,因此就存在了爭論。就像是Java和.NET、PHP和.NET、WebForm和MVC、Mac OS和Windows、iOS和Android、騰訊和全部其餘互聯網公司,等等。
問題不在哪一個更好,而是咱們要解決什麼問題。固然,這聽(ben)着(lai)像(jiu)是客氣話了。
真正在UI和邏輯分化後帶來的實質問題是:
至少UI和邏輯剛分化的時代,在軟件上,咱們還認爲同一項事務是基於同一個UI的一系列操做完成的。
在摩爾定律還持續發揮做用的時候,計算機領域依舊高速發展,因此一般咱們還在爲同樣事物爭論、思考、辯證的時候,它已經發生了質變了,不變的只是咱們要解決的問題。
在以前說到過了,當需求變得龐大,解決方案也會變得龐大;當解決方案變得龐大,就會出現細分;當出現細分,就會出現按哪一種方式管理的問題。
軟件從處理一件事務發展到了要處理許多事務,各事務間有包含、順序、主次等等的關係,變得愈來愈複雜。由於數據與邏輯龐大了,因此數據與邏輯就分離了,而後事件和業務分離了。
它們的關係已經在咱們還理得清以前持續發展而變得更加難理得清,但在一個時間點上,它們UI的領域大體分化成這些原子:
你要細化的話會有更多繁雜的細節,但相信這麼寫的話爭議性比較小。
當一個問題出現一次的時候它是一個問題,當一個問題出現了無數次的時候它會成爲歷史,當一個問題將會出現無數次的時候,它將須要一個明確的定義和解決方案。
其中,數據的更新和界面的更新這一特殊事件的問題被放大了無數倍,由於它出現了無數次。
在ASP還在奮鬥的時候WebForm忽然到來,正如WebForm還在奮鬥的時候MVC忽然到來。固然,我這裏講的MVC仍是最原始的MVC,由於MVC在咱們還在爭論的時候已經發展了許多不一樣分支了。
有一點相信你們贊成的就是,咱們今天討論爭論的MVC、MVP、MVVM、Code Behind等等都源自於職能分化和規劃的思想與目的,MVC不是它們的開始,可是一個很好的開始。
相信MVC的模型你們很熟悉,也很容易找到,咱們這裏用一下某百科的圖:
咱們能夠看到的是,界面被分到了View,數據分到了載體Model上由Model「攜帶」,業務集中在Controller中,而推進業務的事件由用戶與View交互,經過View向Controller發動。
固然,實現由不少種,每種細節上都有不一樣,因此我才只講也只能講大體的MVC。MVC的其中一個缺點即是沒有明確的定義,因此不一樣的實現(好比Struts和http://ASP.NET MVC)細節上都是不同的。
咱們須要知道的是,MVC並非像上面所說的一些事情那樣是一種「必然的」結果,它是一系列必然結果問題中的一種解決方案,並且是不完美的解決方案。咱們順着推理去到一個地方很容易犯的一個錯誤就是認爲路只有這一條而忽視其餘可能性(估計這也是致使不少爭鬥的緣由)。另外,咱們在討論一件事物不完美的時候是有一個情境的,因此請不要像「我說它色彩單一,而後你把它塗成彩色後證實我是錯的」。
MVC的通常流程是這樣的:View(界面)觸發事件--》Controller(業務)處理了業務,而後觸發了數據更新--》不知道誰更新了Model的數據--》Model(帶着數據)回到了View--》View更新數據
這裏也很少再陳述MVC的原理、實踐等等,由於這就太長篇大論了。
像咱們以前推理的,分化是一種需求的必然結果,但卻沒有個一個肯定的結果,好比Code Behind和Code Block的問題等等。
MVC順着需求把UI相關的工做分化成了三份,這點通過實踐證實無可厚非。可是它們的三角關係卻被一些人認爲帶來了一些問題,或者應該說他們有「更好的」解決方案。
在只有Code Behind和Code Block的那個時候維護是很直接的,不是在同一段代碼內解決就是在同一個關聯的事件上解決。三角關係的問題就是維護問題。在MVC,當你有變化的時候你須要同時維護三個對象和三個交互,這顯然讓事情複雜化了。
咱們以前說到,隨着摩爾定律,軟件的需求不斷地變化和變得龐大。隨着需求變得龐大的時候,需求變化也變得頻繁,這是一個出現了無數次之後也將會出現無數的無數次的一個問題,因此它須要一個解決方案,哪怕它不必定能被解決。
爲了解決需求變化,從《人月神話》到敏捷到DDD,它不是咱們已經解決了的問題,而是咱們正在解決的問題。放在UI的模式和MVC上來說,就是優化或者替代MVC模式,其中之一就是Model-View-Presenter(MVP)模式。
咱們先看看兩個MVP模式的圖:
(圖一)
(圖二)
兩幅圖是不一樣的,可是對MVC的改進的思想倒是同樣的:切斷的View和Model的聯繫,讓View只和Presenter(原Controller)交互,減小在需求變化中須要維護的對象的數量。
這種方式很符合咱們的期待,由於咱們傾向於:
許多時候並非一種模式很差,而是由於人沒辦法執行,好比不容易理解,咱們就會選擇容易理解的方式。計算機依賴摩爾定律用數量的增加來解決問題,而人是用方式的改變來解決問題的。一樣由於客觀緣由咱們不善於維護多個對象和多個對象之間的關係,因此咱們改變了,或者說簡化了這種方式。
MVP定義了Presenter和View之間的接口,讓一些能夠根據已有的接口協議去各自分別獨立開發,以此去解決界面需求變化頻繁的問題。上面兩圖都有接口,不過接口的實現和使用細節不同,不過思想上是一致的。
在這裏要提到的是,事實上,需求變化最頻繁的並不必定是最接近用戶的界面,但基本能夠肯定的是,最接近用戶的界面是由於需求變化而須要最頻繁更改的。固然,若是View若是是API而不是UI,那就另說了。
還有一些用來「解決」MVC這項缺點的好比有:http://ASP.NET MVC的ViewBag,Cocoa的delegate。它們都爲了簡化數據更新的問題而存在,包括MVVM。
先直接看看Model-View-ViewModel(MVVM)的圖:
從圖上看是比MVP簡單了,更不用說MVC了。我的不認爲MVVM是從MVP進化而來,我只以爲這是在MVP以後出現的一種「更好的」UI模式解決方案,可是用MVP來與之對比比較容易說明問題。
ViewModel大體上就是MVP的Presenter和MVC的Controller了,而View和ViewModel間沒有了MVP的界面接口,而是直接交互,用數據「綁定」的形式讓數據更新的事件不須要開發人員手動去編寫特殊用例,而是自動地雙向同步。數據綁定你能夠認爲是Observer模式或者是Publish/Subscribe模式,原理都是爲了用一種統一的集中的方式實現頻繁須要被實現的數據更新問題。
比起MVP,MVVM不只簡化了業務與界面的依賴關係,還優化了數據頻繁更新的解決方案,甚至能夠說提供了一種有效的解決模式。
至此,咱們能理解爲何許多人認爲MVVM是最好的一種模式,沒有之一。但事實上,MVVM也是依賴於咱們至今所講的「特有的情境」。
固然,最優雅的也是第一個能做表明的實踐就是Windows Presentation Foundation(WPF)了。
之上,咱們在模式演變的推論基本上都仍是基於桌面軟件的,可是過去十年倒是互聯網的時代。實際上大部分讓你們爭議的並非在桌面領域最合適的是那個,而是在Web領域的模式問題,也就是在B/S場景下的問題。
當軟件離開單機,去到網絡的時候,由於場景變了,因此原有的解決方案也變了,不過需求依然是不變的。咱們依然要解決的問題是用戶交互與數據更新的問題,還有維護等等的問題。
當場景變到Web的時候,咱們發現MVVM用來作服務端是極其不適用的,至少如今是不適用的。而MVP你提都不用提。爲何呢?由於:
問你們一個問題,當一個網頁的數據更新後,你但願更新用戶看到的數據,你會怎麼作?
通常狀況下,你會:
window.location.reload();
就算你不這麼作,用戶也會:
F5
就像以前說的,咱們會選擇更直接的方式解決問題。直接刷新頁面的緣由是由於這樣更直接,更容易解決數據更新的問題。
不少時候你不會願意爲了一個數據更新寫一個AJAX,更別說這個AJAX要帶來Loading、事件順序處理、網絡問題、異常處理等等,這就是開發成本太高。
另外一個網絡成本太高就更容易解釋了,雖然寬帶是基本包月的,但也不帶這麼用的,況且還有移動用戶。更主要的緣由是,在本地軟件,更新數據是一個引用問題,而在網絡應用上,這是一個傳輸問題。傳輸成本遠高於引用成本,引用之上頂可能是在本地內存中再進行一次內存拷貝。
這個時候,咱們會更傾向於用MVC模式,由於在Web層面,咱們更傾向於一次性更新數據。
全部問題都不是問題,就算有問題也要解決問題。
爲何這個標題下忽然冒出這麼一句話?我想說的是,需求依舊是不變的,是推進進步的原動力。
還有我以前說過,當咱們討論或者爭論一個問題的時候,問題的對象已經發生改變了,並且此次是在咱們討論這個問題以前已經發生改變了。
網絡資源成本不斷降低,相信已經不須要多說起。摩爾定律和相近的一些原理正在發揮着它應用的做用,網絡帶寬愈來愈高、相應速度愈來愈快。
若是傳輸由於相對成本降低而致使數據傳輸的成本低於開發人員拒絕客戶的成本,那麼它就會被實現而不是被拒絕。
另外還有一點就是由於技術的進步,技術的資源不斷被更大規模地壓榨,需求也不斷地增加,那麼需求始終會增加超過相對不變的開發成本的。好比jQuery的出現解決了不少問題,咱們如今更多地去使用AJAX,哪怕很大一部分依然是爲了解決網絡資源不足的問題;咱們會用更多的樣式代碼而用了相對更少的圖片;咱們再也不那麼依賴Flash一類的矢量圖解決方案而直接錄製視頻。
至 少上一節咱們說到的兩個致使你們選用MVC的問題都正在被解決,因此咱們有理由相信將來Web不只僅須要MVC,可能會須要MVVM或其餘解決方案。至少 咱們能理解容易理解爲何前端會出現一些MVVM的框架,好比先驅knockout.js和AngularJs。這些框架自己的好壞就不做討論了,由於我 們討論的是模式。
在Web上,MVVM的對比對象就不是MVC,而是Code Block。
數據即時更新的需求在擴大,但未必有達到必定要用MVVM這一等級的高大上的模式,實際上若是你要更新一個數據,你仍是會採起:
$('.notice').html('發送成功!');
由於......咱們依然會採起更直接的方式解決問題......
實際上,如今Web MVVM主要並非用在了Web或者Wap上,而是移動App上。按照前面的說法,只多是:
哪怕是Native開發,實際上iOS的開發上也是用相似的數據綁定的方式的。這裏也不深究了,畢竟我也不算懂iOS。
要說的是,在Web MVVM或者Web的模式上,也就是Web的富應用上,如今還不過是個初期由膨脹的需求推進的階段。重要的不是技術會怎麼走,而是需求和客觀條件會怎麼走。
可能Webform會由於高速開發而煥發第二春,它的AJAX的模式也十分知足於簡單開發,但彷佛你們須要的不是GUI式的網頁。
咱們不必定須要MVVM,但咱們必定須要更強大的方式去解決不斷膨脹的Web需求。
咱們能夠預見的是:
除去客氣話的部分,我仍是想說,在不一樣的需求下其實有最適合的解決方案,一般讓咱們糾結的不是由於哪一個解決方案更好,而是咱們看到的條件不夠多。
編 譯語言固然比解釋語言效率高,但考慮到開發和維護成本,JavaScript等始終會大行其道,好比Node.JS、Python;.NET和微軟固然很 強大,移植.NET到其餘平臺也很容易,但微軟是家有本身商業模式和要賺錢的公司;固然有些實踐和技術更好,但其餘開發人員會避開甚至否認本身不擅長的東 西,你們都喜歡肯定的東西;有些技術更強大,可是隻是基於特殊的客觀條件和需求,若是你想作大,要麼創造客觀條件,要麼把它結合需求......