監督控制器

將 UI 分解成檢視和控制器,其中檢視處理對底層模型的簡單對應,而控制器處理輸入回應和複雜的檢視邏輯。

2006 年 6 月 19 日

這是 進一步的企業應用程式架構開發 的一部分,我在 2000 年代中期撰寫。很遺憾,從那以後有太多其他事情吸引了我的注意力,所以我沒有時間進一步處理它們,而且在可預見的未來我也看不到太多時間。因此,這份材料很大程度上仍是草稿,直到我找到時間再次處理它之前,我不會進行任何更正或更新。

許多 UI 框架提供了在檢視和模型之間輕鬆對應的能力,通常使用某種 資料繫結。這些方法非常有效,可讓您宣告性地設定檢視和模型中元素之間的關係。然而,通常有更複雜的關係,需要您有更複雜的檢視邏輯。這種邏輯可能難以管理,特別是嵌入在檢視中時難以測試。

監督控制器 使用控制器來處理輸入回應,但也用於操作檢視來處理更複雜的檢視邏輯。它將簡單的檢視行為留給宣告性系統,僅在需要無法宣告性達成的效果時才介入。

運作方式

監督控制器 將簡報功能分解成兩個部分:控制器(通常稱為簡報者)和檢視。需要顯示的網域資料是分開的,並且遵循粗略的 MVC 術語,我將其稱為模型,儘管它不必是 網域模型。責任的基本劃分呼應了 Bower 和 McGlashan 所描述的海豚形式的模型-檢視-簡報者架構。

一個 Supervising Controller 有兩個主要職責:輸入回應和部分檢視/模型同步。

對於輸入回應,控制器以簡報者的樣式操作。使用者手勢最初由螢幕小工具處理,然而他們在回應中所做的,就是將這些事件傳遞給簡報者,簡報者處理所有進一步的邏輯。

對於檢視/模型同步,控制器將此盡可能合理地委派給檢視。檢視通常使用某種形式的 資料繫結 來填入其欄位的許多資訊。如果 資料繫結 無法進行更複雜的互動,則控制器會介入。

圖 1:評估範例的類別圖。

圖 2:顯示輸入低實際值的回應的順序圖。

在評估視窗中,初始文字變更由檢視中的文字欄位小工具處理。這個小工具由控制器觀察,因此當文字變更時,小工具會發出一個事件,導致呼叫控制器的 actualFieldChanged 方法。然後這個方法處理對事件的完整回應。它首先更新讀取模型物件的實際值。視窗觀察讀取物件,因此讀取值的變更會觸發更新。將實際和差異文字欄位的文字對應到讀取的適當屬性非常容易,因此會更新那些值。就我們的範例而言,變更顏色會更複雜一些。讀取物件可以而且應該確定讀取應符合哪個類別。一個精密的小工具或許可以將其文字顏色繫結到像這樣的類別,但我們假設我們沒有這麼聰明的東西。在這種情況下,控制器會直接接管設定差異欄位的文字顏色。

正如範例所示,一個好的 Supervising Controller 的精髓是盡可能少做。讓檢視盡可能處理,只有在涉及更複雜的邏輯時才介入。

使用 Supervising Controller 的主要原因之一是為了可測試性。假設檢視難以測試,透過將任何複雜邏輯移到控制器中,我們將邏輯放在一個較容易測試的地方。然而,為了對控制器執行測試,我們確實需要某種形式的檢視,因此通常需要一個 測試替身。有了替身,我們就不需要 UI 架構物件來測試 UI 行為中比較棘手的部分。

這個可測試性問題影響另一個決定 - 控制器是否應直接存取檢視及其小工具,或透過中間人。有了中間人,我們為控制器建立一個 閘道。閘道定義控制器用於操作的介面。然後,一個實作會調整視窗的介面,而另一個實作則提供一個測試用的 stub(你也可以使用模擬)。這是 被動檢視 所需的相同方法。

圖 3:在控制器和視窗之間使用中間人。

到目前為止的討論建議將 流程同步監督控制器 搭配使用,但這不一定是必要的。可以改用 中介同步,但需要修改,以便由控制器觀察模型,而不是檢視。

何時使用

考慮使用 監督控制器 的主要原因有兩個:將 自主檢視 的複雜性分開,以及改善可測試性。

分離的優點是,它將所有行為複雜性從基本視窗本身抽離,使其更容易理解。此優點的缺點是,控制器仍然與其畫面緊密結合,需要對畫面的詳細資料有相當深入的了解。在這種情況下,是否值得花費精力使其成為一個獨立的物件,是一個真正的問號。

可測試性的原因更具說服力。我交談過的許多人發現,使用某種形式的控制器對建立一個可適當測試的 UI 有很大的幫助。

如果可測試性是你的驅動力,那麼驅動問題就是將多少行為留在檢視中。 被動檢視監督控制器 的模式非常相似,但不同的是,被動檢視 將所有檢視更新行為放在控制器中,包括簡單的情況。這會導致額外的程式設計,但表示所有簡報行為都是可測試的。兩者之間的選擇取決於你擁有的 資料繫結 支援類型,以及你是否願意讓控制器測試不測試它。

第三個替代方案是 簡報模型。這再次將大部分行為從檢視中抽離,但讓檢視同步其所有更新。在 簡報模型監督控制器 之間的測試涵蓋範圍沒有太大的差異 - 大部分的選擇(與 被動檢視 一樣)取決於個人判斷。