簡體   English   中英

我應該在不同的視圖中重用視圖模型嗎?

[英]Should I reuse view models in different views?

我注意到我的視圖需要與其他人一樣的信息。 但有時你需要視圖模型的 5 個屬性,有時只需要 2 個。

您是在多個視圖上共享這樣的視圖模型,還是為每個視圖創建單獨的視圖模型,或者您是否更喜歡繼承組合策略?

對我來說,共享視圖模型有一些缺點:

  1. 最小驚喜原則:一個視圖模型只填充5個的2個屬性,得到空引用異常,很奇怪,因為你不想查詢數據庫的額外數據。 當視圖模型有 5 個屬性時,我希望所有屬性都被填充。 例外證明了規則。
  2. 關注點分離/單一職責原則:視圖模型在復雜站點上雜亂無章,因為您必須滿足每個視圖的不同需求。 如果涉及邏輯,它也會變得更加復雜。

你怎么認為? 你如何處理這樣的情況?

人們傾向於根據他們使用的觀點對 ViewModel 有不同的理念。 ViewModels 是視圖和模型之間的粘合劑,人們通常會根據他們喜歡更嚴格的兩端中的哪一個來回答。

  • 如果你喜歡你的模型/數據對象更嚴格,那么你會傾向於將 ViewModel 與模型/數據聯系得更近——也就是說,你將有一個在多個視圖中使用的 ViewModel,並讓 ViewModel 確定哪些屬性根據您希望如何處理數據加載進行檢索(並推遲圖像或其他長時間加載屬性等)。
  • 如果您希望您的視圖更加嚴格,那么您可以將 ViewModel 與 View 聯系在一起,即每個視圖都有一個單獨的 ViewModel,並讓模型/數據對象在您從一個視圖移動到另一個視圖時處理諸如同步之類的事情。

就我個人而言,我更喜歡第一個,因為我的數據往往更嚴格,因為它比視圖更不可能改變(在我的項目中 - 我不認為這是數據和視圖的普遍屬性)。 由於更改通知是 ViewModel 的一個自然功能,如果用戶碰巧有兩個顯示相同/相似數據的視圖,我不必讓我的模型對象傳達更改。

在我正在處理的項目中,每個視圖都有自己的 ViewModel,但是我們也有 CollectionViewModel,它們被多個視圖模型共享/引用。

想想——一個供應商列表,需要在你的應用程序的多個屏幕中顯示——並且綁定到各種控件——一個列表框、網格視圖,無論你需要什么。 只有一個 ViewModel 可以簡化供應商列表的更新/刷新邏輯。

TLDR:如果所有用例都以相同的方式使用 ViewModel,我只會重用視圖模型。 即它們都使用相同的屬性等。

對於每個視圖,我都會有一個單獨的 ViewModel。 未使用的屬性會降低代碼的可讀性(如果不使用該屬性,為什么會出現該屬性?)。 如果您對多個視圖上的一組固定屬性具有相同的功能,我可以看到使用包含這些屬性的基類。

每個視圖肯定有一個 ViewModel,恕我直言。

隨着您的應用程序復雜性的增加,共享 ViewModel 將趨於增長,並且當它只需要一個屬性時,將具有 50 個屬性的對象傳遞給 View 感覺不太好。

此外,有時您可能希望在您的 ViewModel 中添加額外的屬性,這些屬性絕對特定於您的視圖,並且您在其他視圖中不需要。 假設您有一個依賴於 ViewModel 屬性的 CSS 類。 您無需在 View 中編寫 if else 語句,而是在 ViewModel 中創建一個屬性,該屬性根據您擁有的任何業務規則返回正確的 css 類。 通過這種方式,您可以使 View 盡可能纖薄,並且使用專用的 ViewModel 您不會與並不真正關心它的 View 共享 CSS 類名。

我通常共享 ViewModel。 據我了解,使用視圖模型的優點是 (a) 安全性,因為應該隱藏的屬性是 (b) 業務層和表示層之間的關注點分離。 (b) 在共享視圖模型時完成相同的操作。

至於(a),我很少遇到在一個地方暴露財產是安全風險而在另一個地方不存在的情況。 如果一個屬性需要隱藏,它可能需要在任何地方隱藏。 當然,YMMV,但這似乎是一個相當主觀的問題。

我將實體框架與 Code First 一起使用,因此我的域類需要保持非常嚴格,因為它們將被映射到 sql 數據庫。

有些視圖只使用一個直接映射的實體,這很好,所以我使用相同的域層實體。 如果該實體需要更多信息(例如兩個密碼字段),我將使用組合。 '組合應該優先於繼承',所以如果你可以使用組合,通常因為它只是附加屬性,可以使用組合。

如果有一個屏幕只使用該實體的兩個屬性,或者我出於安全考慮想要隱藏屬性,我會創建一個新的視圖模型並且只檢索必要的數據。 我將重用視圖模型,但前提是其他視圖中需要相同的屬性。

僅當所有視圖都使用所有屬性變量和方法時,我才會在多個視圖之間共享 VM,否則我將使用繼承和抽象基本視圖模型,如果這不能解決。 做 1 對 1

TLDR:是的(如果您真的想使用它並知道如何明智地使用它)。

我可以想到視圖模型層需要的三個職責:

  1. 將視圖層和模型層耦合在一起
  2. 提供單元測試接口
  3. 當單個頁面很復雜時將邏輯分成小塊

第一個責任實際上與第二個責任相沖突。 因為一旦視圖模型知道(耦合)要啟動的視圖類,就無法對其進行單元測試。 知道要啟動的模型(及其提供者)類不會導致此問題。 但是,如果提供者是單身人士,則單元測試將變得不那么“單元”。

當談到第三個職責時,有一種我稱之為路由的邏輯。 例如,單擊按鈕后,用戶應該看到下一頁。 這種邏輯應該在哪一層? 看法? 模型? 當然不! 它無處可去,只能查看模型。 一旦一個視圖模型知道下一個要啟動的視圖模型的類,它就會生成一個巨大的視圖模型樹來處理。 因為這是遞歸發生的——下一頁也知道下一頁。 無論這個視圖模型樹中的哪個節點,一旦發生變化,它就會反映在父節點上。 如何處理這些反射? 子類化? 請記住,在樹中,一個節點可以有數百個直接/間接子節點。

結論 - 只有當它放棄第一個責任時,視圖模型才擅長第三個責任。 它唯一真正擅長的是第二個責任。 但是,我看到沒有人在這個問題下提到它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM