UI 架構 - 讀Martin Flower相關文章總結

近來看了大師Martin Flower的一些關於UI 架構的文章,爲了加強理解特總結如下。


大師從設計的角度入手,闡述了UI 架構的具有代表性跟影響力的模式。其中當然提到了MVC此耳熟能詳的模式。並從MVC的源起和演化爲我們澄清了對MVC的理解。除了MVC, 大師對UI 架構的其他模式也進行了總結歸納。下面此文簡要總結大師對各模式的評述。


1. Forms and Controls
此模式出現於client-server應用盛行之時,晚於MVC的出現。同學們接觸過VB, VC, Delphi 跟 PowerBuilder, 應對此不陌生。


Control 就是我們說的 控件(注意不要混淆controller)。 控件是可重用,但跟具體業務邏輯和具體數據不相關的單元。


Form 是特定應用邏輯相關的,跟很多控件相關聯,能完成某獨立功能的單元。
我們要注意區分Form 跟 自定義控件。 因爲自定義的控件可以由多個控件組合而成。 但是Form是跟特定業務邏輯相關的。
界定Form, 可以從Form的兩個職責入手。 
Form 的 第一個職責就是, Form要負責佈局的管理。
             第二個職責就是 Form 負責業務邏輯的處理,雖然控件可以承擔一些邏輯,但一定存在一些邏輯行爲是不能被控件所實現的,有可能是重用的考慮。Form爲了完成業務邏輯還需協調各個控件的行爲。


在數據層面上,此模式視數據爲三層存在。 最終被共享的數據存於數據庫中,論文定義爲 record state。 論文定義session state 爲record state的內存拷貝,之所以冠以session是應爲此拷貝是基於應用程序跟數據庫的特定的session。最後就是用戶看到的screen state。

成熟的Forms and Controls 模式的實現 一般給予 Data Binding, Event framework, Observer 模式來同步數據的三種狀態。 數據同步由Form協調進行。


此模式的關鍵點:

- 編寫應用邏輯相關的Form, Form由控件組合而成;

- Form負責其上的控件的佈局;

- Form偵聽其上的控件所觸發的事件,並且對事件做出相應的反應;

- 簡單的數據改動通過綁定機制進行同步;

- 複雜的邏輯在Form的偵聽方法裏進行處理。


2. MVC

MVC概念最早起源於smalltalk。 是最爲同學們唸叨的一個模式。但最早的經典的MVC概念已經與現在的富客戶端有代溝了。所以也導致對這個概念的一些不同的理解跟誤用。

尋根追脈,從smalltalk的MVC說起。

這裏最關鍵的是Separated Presentation。而 Separated Presentation的關鍵就是劃分(Domain Object)領域對象跟展示對象(Presentation Objects,不要與下面提到的Presentation Model混淆啊)。Domain Object 是對真實世界,業務領域的模型。Presentation Object是GUI所體現的數據元素。根據Separated Presentation的定義,領域對象要完全獨立於展示(Presentation),在獨立的前提下可以支持同一數據同時對應多個展示。

注意:我們看到對數據的定義有着完全不同於Form and Control的叫法。Form and Control裏是Record State, Session State跟Screen State。 之所以有差異,是我們看數據的角度不同。Form and Control模式對數據的定義基於一個假設,假設就是開發人員是大量基於數據庫記錄進行開發。MVC假設操作對象是Object。


上面通過核心概念Separated Presentation的描述,我們已經分析出了Model這個概念。剩下View和Controller這兩個概念,接着看。

Controller的職責是根據用戶的動作規劃出怎樣處理應對。在View/Controller上需要強調的是,一個應用包含有很多的View-Controller對。在smalltalk的MVC的概念中View-Controller對構成一個組件(component)。View跟Controller一同組成展示部分。


Smalltalk的MVC上,數據更新通過Controller更新到Model。另一方面View通過Observer得到Model的更新。注意這裏跟Form and Control有很大不同。Flow and Control以Flow Synchronization( 屏幕代碼直接,直觀地更新model,直接通知共用此模型的其他控件。但這樣也導致了屏幕代碼之間的耦合。適合一些簡單的界面,例如,root-child風格的模態框,我們關閉模態框直接通知到他的root窗口,這樣很直接。)的方式進行數據同步。MVC以Observer Synchronization(適合統一分數據同時對應多個屏幕,但代碼相對更難理解)進行同步。


討論完了數據同步問題,接下來對於MVC還有一個些尷尬的問題。闡述這個問題,我們從例子引入,如果我們的model有兩個值,根據兩個值的差值的範圍來設置某一控件的顏色。計算差值,進一步把差值映射到具有領域意義的屬性,這部分職能由model負責,並不難理解。但是從model的屬性再映射到顏色的顯示這相關邏輯應該放在何處? 在早期的smalltalk裏,這個問題的解決方式就是打破領域模型的純潔性,把這部分邏輯參合進領域模型中。這是一種不優雅的做法,但我們可以偶爾爲之 :)。另一種相對好的做法就是,我們封裝自己的控件,控件中包含一張值與顏色的對照表,這部分映射邏輯就封裝進自定義控件。這種做法的前提是我們要可以很方便地subclass要封裝的控件。最後還有一種做法是我們可以添加一種新的model對象。這種對象面向顯示,其中要用到領域對象的部分通過代理(delegate)實現。我們稱這模型爲展示模型(Presentation Model)。


我們再來彙總一下MVC重要之處:

- Sparated Presenation, 展示(View 跟 Controller)要嚴格區分 模型(model).

- 把GUI Widget分成View跟Controller,他們共同組成widget。 Controller負責(單獨,直接)反應用戶的請求,點擊。View負責顯示狀態。View跟Controller通過Model進行交互。

- 通過Observer Synchronization, 讓View對Model進行同步。同時支持一份數據對應多個View。


3. MVP (Model-View-Presenter)

這個模式最早出現於IBM。常見於上世紀90年代一面向對象操作系統Taligent。


MVP試圖融合前兩種模式的優勢。Form and Control的簡單直觀。MVC的支持同意數據上的多View。

下面我們通過比較來闡明MVP。

跟Form and Control對比,MVP的View更像Control。View直接接收用戶的刺激再轉手給Presenter。

跟MVC比。MVP的展示部分不分爲View/Controller兩部分,MVP的View就是展示部分。Presenter可爲Supervising Controller,但不同於MVC的Controller, Presenter不直接反應用戶刺激。用戶刺激都是·經View轉手到Presenter。在不好適用Observer Synchronization的時候,Presenter可以直接操作顯示組件。

MVP的Presenter跟MVC的Controller存在很大的相似性。Presenter是一種鬆散形式的MVC Controller。所以在很多框架實現中,實現的雖然是MVP風格,但Presenter被叫作Controller。


要點總結:

- View部分widget直接接受用戶刺激,再轉手給Presenter.

- Presenter再負責協調model的改變。

- 在處理View的更新問題上,此模式相當寬鬆。各種實現都可以,從使用Observer Synchronization到直接由presenter更新。


4.Humble View

Humble View的出發點是測試。尤其敏捷開發,我們流行寫自測試的代碼(Self-testing)。而UI的測試在這方面一直比較尷尬,原因是UI代碼直接跟展示基礎平臺耦合。這種情況下,很多研究極力最小化那些難以測試的對象行爲,這就是Humble Object。


前面幾節中我們提到的Presentation Model跟Supervising Controller都朝這個方向做出了相應的貢獻。我們可以測試Presentation Model跟Supervising Controller,剩下humble object裏的邏輯就難以覆蓋到了。在Presentation Model情況下,所有的邏輯決策都由Presentation Model負責。所有用戶事件跟顯示邏輯都被路由到Presentation Model。Widget只負責映射到Presentation Model的屬性。這部分映射很難Self-testing。在Supervising Controller中這種不能Self-testing的映射可以控制在更小的範圍內,原因是Supervising Controller將不需要映射來操作widget來應付一些複雜的情形。


還有一個爲測試而生的模式,這裏要提到的就是Passive View(MVC跟MVP的變種)。它在Humble Object上做出了最大努力。Passive View不僅用Controller來反應用戶事件,還用它來更新View(跟MVC相比,這裏View不再依賴Model)。這樣UI組件的邏輯行爲被減少到了最少(相對Presentation Model跟SuperVising Controller,因爲這兩個還需要View來負責更新)。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章