學習ASP.NET MVC架構揭秘筆記-PV與SC,mvc-pv
1. PV與SC解決View難以測試最好的辦法就是讓他無須測試。如果View不需要測試,其先決條件就是讓它儘可能不涉及UI處理邏輯,這就是PV模式的目的所在。
如果我們純粹的採用PV模式來設計View意味著我們需要將View中的UI元素通過屬性的形式暴露出來。具體來說,當我們為View定義介面的時候,需要定義基於UI元素的屬性使Presenter可以對View進行細粒度操作,但這並不意味著我們直接將View上的控制項暴露出來。
舉個例子,假如我們開發的HR系統中有這樣一個介面,介面上有一個包含所有部門列表的DropDownList,還有一個是顯示員工列表的GridView,還有一個查詢按鈕,我們可以通過查詢按鈕來講選擇的部門的員工顯示出來。
如果為該View定義一個介面IEmployeeView我們不能如下所示的代碼將上述的兩個控制項直接以屬性的形式顯示出來。針對具體控制項類型的資料繫結屬於View的內部細節,不能體現在表示用於抽象View的介面中。
public interface IEmployeeView{<span style="white-space:pre"></span>DropDownList Departments{ get; }<span style="white-space:pre"></span>GridView<span style="white-space:pre"></span> Employees { get;}}
正確的介面和實現該介面的View應該採用如下的定義方式:Presenter通過對屬性Departments和Employees賦值來實現對相應DropDownList和GridView的資料繫結,同時通過屬性SelectedDepartment得到使用者選擇的篩選部門。為了儘可能讓介面只暴露必需的資訊,我們還特意將對屬性的讀/寫作了控制。
public interface IEmployeeView{<span style="white-space:pre"></span>IEnumerable<String>Departments{ set;}<span style="white-space:pre"></span>StringSelectedDepartment{ get;}<span style="white-space:pre"></span>IEnumerable<Employee><span style="white-space:pre"></span>Employees{ set;}}public partial class EmployeeView : page , IEmployeeView{<span style="white-space:pre"></span>public IEnumerable<string> Departments<span style="white-space:pre"></span>{<span style="white-space:pre"></span>Set<span style="white-space:pre"></span>{<span style="white-space:pre"></span>this.DropDownListDepartments.DataSource = value;<span style="white-space:pre"></span>this.DropDownListDepartments.DataBind();<span style="white-space:pre"></span>}<span style="white-space:pre"></span>} <span style="white-space:pre"></span>public string SelectedDepartment<span style="white-space:pre"></span>{<span style="white-space:pre"></span>get{<span style="white-space:pre"></span>return this.DropDownListDepartments.SelectedValue;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public IEnumerable<Employee> Employees<span style="white-space:pre"></span>{<span style="white-space:pre"></span>set<span style="white-space:pre"></span>{<span style="white-space:pre"></span>this.GridViewEmployees.DataSource = value;<span style="white-space:pre"></span>this.GridViewEmployees.DataBind();<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}}
PV模式將所有的UI處理邏輯全部定義在Presenter上,意味著所有的UI處理邏輯都可以被測試,從可測試性的角度來看這是一種不錯的選擇。但它要求將View中可供操作的UI元素定義在對應的介面中,對於一些複雜的富用戶端(Rich Client)應用的View來說,介面成員的數量可能會變得很多。另外,由於Presenter需要在控制項層級對View進行細粒度的控制,這往往會使原本簡單的邏輯複雜化。這種情況下我們往往採用SC模式。
在SC模式下,為了降低Presenter的複雜度,我們傾向於將諸如資料繫結和顯示資料格式化這樣簡單的UI處理邏輯轉移到View中,這些處理邏輯會體現在View實現的介面中,儘管View從Presenter接管了部分UI處理邏輯,但Presenter依然是整個三角關係的驅動者,View被動的地位依然沒有改變。對於使用者作用在View上的互動操作,View本身並不進行響應,它只會將互動請求轉寄給Presenter,後者在獨立完成相應的處理流程(可能涉及針對對Model的調用)之後會驅動View對使用者互動請求進行響應。