MVVM模式在嵌入式GUI AWTK 中的實現

AWTK-MVVM是一套爲AWTK用C語言開發,並支持各種腳本語言的MVVM框架,實現了數據綁定、命令綁定和窗口導航等基本功能,使用AWTK-MVVM開發應用程序,無需學習AWTK本身的API,只需學習綁定規則和Model的實現方式即可。

1.1 分離用戶界面和業務邏輯

在開發應用程序時,要把用戶界面和業務邏輯分離開來,這是每個程序員都知道的常識。分離用戶界面和業務邏輯有幾個重要的好處:

  1. 有利於隔離變化。用戶界面是最容易變化的,易用性的改進,外觀的美化和需求的變化,首先衝擊的就是用戶界面。如果用戶界面和業務邏輯耦合到一起,界面上一點微小的改動都會導致一系列代碼的修改,這不但會增加開發的成本和週期,而且這種改進也是很無趣的,讓程序員的幸福感直線下降。

  2. 有利於自動測試。代碼中的BUG,越早被發現,修改的成本越低,而單元測試是在早期發現BUG的重要手段。單元測試是自動化的,前期編寫測試代碼的投入,會因爲後期節省測試的時間而獲得回報。單元測試代碼可以不斷積累,爲軟件構建一道堅固的防火牆,讓整個系統越來越穩定。分離用戶界面和業務邏輯是提高代碼可測試性的重要手段,讓編寫單元測試程序成爲可能。

  3. 有利於分工合作。用戶界面和業務邏輯的耦合,會讓用戶界面的修改很困難,程序員就會抵觸用戶界面的改動,讓設計師和程序員之間的矛盾加大。分離用戶界面和業務邏輯後,設計師的工作成果可以平滑的輸出給程序員,讓程序員和設計師一起過上共同幸福的生活。

1.2 如何分離用戶界面和業務邏輯

分離用戶界面和業務邏輯,MVVM是目前最常用的模式。MVVM並非憑空出現,而是由MVC和MVP一路演化而來的,每次演化都是爲了解決之前沒有解決的問題。

1.2.1 MVC模式

MVC是Model-View-Controller簡稱,它首次把系統分成Model,View和Controller這三部分,明確的把用戶界面和業務邏輯分離開來:

mvc

  • 模型(Model)。簡單的說,模型就是業務邏輯。我們經常說面向對象的設計和建模,所建立的模型就是這裏的模型,是對現實世界中業務邏輯的抽象。面向對象的建模,就是要找到業務邏輯中有哪些類以及這些類之間的關係。類描述了對象的屬性和行爲,類是設計時的概念,對象是運行時的概念。對象通常就是業務實體,Model包含一個或多個業務實體。很多人(包括國內一些知名的專家)認爲模型就是數據,這是沒有透徹理解面向對象的設計導致的,對象是即有數據又有行爲的,光有數據沒有行爲,就無法讓對象之間協作,無法共同完成業務邏輯。

  • 視圖(View)。這個是大家都知道的,就是用戶與軟件交互的界面,對於GUI應用程序來講,就是窗口和對話框,以及上面的各種控件。視圖應該說是爲用戶提供了一個界面,讓用戶可以觀察和操作模型。

  • 控制器(Controller)。控制器負責解釋來自用戶通過鍵盤/鼠標等設備的輸入,並通知模型和視圖做出相應的改變。在GUI應用程序中,直白的說,其實就是控件的事件處理函數,它與界面相關和模型都相關,它從界面獲取數據,然後調用模型的函數,有時還會直接更新用戶界面。

控制器(Controller)不是業務邏輯,理論上只是很薄的一個膠合層,但是很多新手把業務邏輯寫在控制器裏,導致模型只剩下數據了,讓人產生控制器就是業務邏輯,模型就是數據的錯覺。

1.2.2 MVP模式

MVC模式解決分離用戶界面和業務邏輯的問題,但是還有一個重要的問題沒有解決: 控制器是界面相關的,沒有辦法爲控制器編寫單元測試程序。爲了解決上面的問題,MVP模式應運而生。MVP是Model-View-Presenter簡稱。

mvc

  • 模型(Model)。模型還是MVC中的模型,這裏不再贅述。

  • 視圖(View)。視圖還是MVC中的視圖,但它不需要向模型註冊改變的事件通知了,這個由呈現邏輯去做了。

  • 呈現邏輯(Presenter)。Controller變成了Presenter只是表面現象,最重要的是MVP對視圖進行了抽象,呈現邏輯不再向控制器那樣直接訪問具體的視圖了,而是通過視圖的接口去訪問視圖,視圖的接口是抽象的,可以有不同的實現,所以可以方便的Mock出一個視圖,讓編寫呈現邏輯的單元測試程序成爲可能。注意,這裏視圖的接口並不是通用的,每個視圖都有一個獨立的接口,有一個真正的實現和一個用於測試Mock的實現。

從理論上講,MVP模式已經很完備了,它很好的分離的界面和實現,也可以爲呈現邏輯編寫單元測試程序了。但是從工程角度來看,MVP卻有一個非常致命的缺陷:要編寫大量無聊的代碼!

爲了方便說明,我們以一個編輯圖書信息例子,看看要寫哪些無聊的代碼。這個例子非常簡單,卻要寫不少無聊的代碼:

  • 1.初始化的時候,要爲控件註冊事件處理函數,比如爲『保存』按鈕註冊事件處理函數。

  • 2.初始化的時候,要把圖書信息,如書名、作者和出版社等信息從模型中取出來,一個一個的設置到視圖的控件中去,在這個過程中,可能需要對數據格式進行轉換,比如出版日期,在模型中是一個整數,在視圖上表現爲一個字符串,這就需要轉換。

  • 3.在編輯結束時,要從視圖中把圖書信息,如書名、作者和出版社等信息一個一個的取出來,再保存到模型中去。在這個過程中,可能需要對數據格式進行轉換,比如前面的出版日期,要把視圖中的字符串轉換回模型中的整數。

  • 4.View都有一個接口定義,有一個真正的實現和一個Mock的實現。

這些代碼很簡單卻很無聊,在每個有界面的模塊中,都遵循同樣的規律,卻又完全不同,不得不重新編寫。

1.2.3.MVVM模式

把MVP模式這些規律找出來進行抽象,通過一些規則在視圖和模型建立聯繫,也就是數據綁定和命令綁定,就形成了MVVM模式。MVVM是Model-View-ViewModel簡稱。在MVVM中:

  • 模型(Model)。模型還是MVC中的模型,這裏不再贅述。

  • 視圖(View)。視圖還是MVC中的視圖,但它不需要向模型註冊改變的事件通知了,這個由數據綁定去做了。

  • 視圖模型(ViewModel)。 ViewModel不是Controller也不是Presenter,視圖模型是視圖還是模型?按MVVM的發明者John Gossman的話說,視圖模型是視圖眼中的模型。放大鏡下的蟲子還是蟲子,所以視圖眼中的模型還是模型。視圖模型與視圖沒有直接關係,是可以爲之編寫單元測試的。

呈現邏輯Presenter去哪裏了?呈現邏輯從一行行代碼變成了一條條數據綁定和命令綁定的規則,對規則的處理和解釋成了MVVM框架或公用庫,可以在多個項目中共享。

mvvm

MVVM模式有下列好處:

  • 強制分離用戶界面和業務邏輯。在MVC和MVP中,不能強制分離用戶界面和業務邏輯,程序員的一念之間,就導致用戶界面和業務邏輯混在一起。MVVM中不需要編寫界面相關的代碼,自然沒有辦法讓用戶界面和業務邏輯耦合到一起。

  • 界面描述文件和程序代碼之間具有更鬆的耦合。通常用XML或RC文件來描述界面,在MVC和MVP中,在界面上增加一個控件或刪除一個控件,都會導致相應的代碼需要修改。而在MVVM中,採用了面向意圖的編程,界面上表現的只是一種意圖,至於在程序中,誰去實現,怎麼實現,甚至有沒有實現,界面都是不關心的,所以界面和代碼之間值的耦合是很鬆的。

  • 不需要學習GUI的API。通過數據綁定和命令綁定建立視圖和模型之間的聯繫。用聲明式的規則取代命令式的代碼,不需要寫界面相關的代碼,所以不需要學習GUI的API,無論是採用Qt還是AWTK,都用同樣的方式開發。

視圖模型和模型並不相同,之所以要引入視圖模型,主要原因有:

  • 模型中的數據有時並不適合直接顯示在視圖上。比如出版日期,在模型中是整數,直接顯示出來,用戶就看不懂,需要轉換成人類可以理解的字符串。

  • 模型中的一個數據項可能以多種形式呈現在視圖上。比如出版日期,除了顯示出版日期外,也可能把最近出版的書,顯示一個新書標誌。

  • 視圖中的輸入數據和模型中的存儲數據,它們的格式有時可能不同。比如出版日期,視圖上輸入的格式和模型裏存儲的格式就不一樣。

  • 視圖需要視圖模型提供數據校驗規則來判斷視圖上的輸入是否合法。

  • 有些數據是有依賴關係的。比如在輸入收貨地址時,選擇省份時,城市列表跟着變化。

  • 有些狀態不屬於業務邏輯,但是需要保存下來。如爲了支持撤銷操作,需要保存命令歷史記錄。

  • 在C/C++等靜態語言中,沒有辦法通過函數的名稱去調用對象的成員函數,也沒有辦法通過屬性的名稱去訪問對象的成員變量。視圖模型需要提供一種機制來實現這些功能,否則綁定規則就沒法實現。

MVVM 的缺點。

  • 內存問題。據說WPF內存開銷很大,即使在PC上也大得讓人無法忍受(常有人藉此來反對MVVM)。WEB前端流行的MVVM框架,像React和Vue.js等,採用虛擬DOM的方式,內存需求可能有大幅度增加。

  • 性能問題。MVVM通常的做法是,模型有變化時會刷新整個界面。如果採用虛擬DOM的方式,還需要重新構建一個虛擬DOM,與原來的虛擬DOM比較,性能開銷就更大了。

  • 調試問題。如果沒有工具的協助,數據綁定會讓調試變得困難。

以上這些問題在手機和PC上,已經不是什麼大問題了,但對於嵌入式系統來說,仍然是難以跨越的障礙,所以目前幾乎沒有針對嵌入式平臺開發的MVVM框架。

1.3 AWTK-MVVM

AWTK-MVVM是一套用C語言開發的,專門爲嵌入式平臺優化的MVVM框架。它實現了數據綁定、命令綁定和窗口導航等基本功能,使用AWTK-MVVM開發應用程序,無需學習AWTK本身的API,只需學習綁定規則和模型的實現方式即可。

與其它MVVM框架相比,AWTK-MVVM特點有:

  • 代碼小。

    • 核心代碼:約3000行。
    • AWTK相關代碼:約700行。
    • jerryscript相關代碼(可選):約1700行。
  • 性能高。核心代碼用C語言開發,其性能與直接使用AWTK差別不大。

  • 內存開銷小。

    • 一條綁定規則大概需要150字節。一個窗口上若有10條綁定規則,內存佔用了也就1.5K。
    • 列表中的綁定規則可以共享,額外增加的內存開銷,比例也是很小的。
  • 隔離更徹底。在AWTK-MVVM中,界面和綁定規則在XML中描述,開發應用程序時只需要開發模型(也就是業務邏輯)即可。除非通過特殊手段,開發者沒有機會直接去訪問視圖。

  • 易調試。

    • 提供視圖模型的框架生成工具,避免手寫代碼造成的錯誤。
    • 增加了各種異常處理的LOG信息。
    • 提供大量的demo以供參考。
    • 開放源碼,調試方便。
  • 支持多語言開發。

    • 目前支持C語言和JS。
    • 以後會根據需要支持新的編程語言。

這裏支持的多種編程語言與AWTK的腳本綁定是完全不相關的概念:這裏是讓應用程序的業務邏輯可以用不同的語言來開發,而AWTK的腳本綁定是讓應用程序可以使用不同的腳本語言來調用AWTK的API。

  • 可移植到其它GUI。AWTK-MVVM是爲AWTK設計的,但是我們隔離了與AWTK相關的代碼,讓它可以移植到其它GUI。AWTK相關的代碼僅僅700來行,可見移植到新的GUI是非常容易的事情。當然,AWTK可以滿足常見的需要,這樣做只是給開發者提供更多選擇。

AWTK-MVVM也有些限制,目前不支持界面元素動態生成,這時可以結合傳統的方法開發。以後AWTK會支持WEB前端流行的框架如Reactjs和Vuejs,在高端平臺(如手機、小程序和桌面程序)中應用。

在後面的章節中,我們將詳細介紹AWTK-MVVM的具體用法。

發佈了679 篇原創文章 · 獲贊 201 · 訪問量 428萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章