使用DDD澄清MVVM

banq發表於2018-11-29

很多MVVM的問題通常是相同的:什麼應該是模型,什麼應該是ViewModel?我們不能真正責怪開發人員,因為線上參考文件不是很好,特別是MSDN的。對於大多數開發人員來說,簡化說明是可以理解的。結果是過於簡化的模式,不適合複雜的業務應用程式。
MVVM有許多相互矛盾的實現。多年以來,我將在這篇文章中描述一個有效的實施方案。

問題根源 
每個人都同意ViewModel定義:它是View的抽象。這種抽象讓GUI更容易測試,我們不需要執行解決方案就可以單獨測試ViewModel。它將UI設計與UI行為分離。

但是這個ViewModel抽象應該是什麼,真的不清楚。通常,實現是一個ViewModel,我們在其中放置了太多的業務邏輯和一個簡單的POCO模型(主要是因為ORM)。

在這種情況下,出現了一個問題:當我在一個ViewModel中只使用一個Model時,我是否需要一個ViewModel?難道我直接繫結模型並通知View是否更新了其中一個屬性?

使用DDD澄清MVVM

 DDD來救援
域模型是來自域驅動設計(DDD)的戰術模式,它可以使模型適合MVVM。使用DDD,我們希望避免使用貧血模型模型可能是MVVM實現的內容。

ViewModel只是View的抽象,它操縱著業務邏輯所在的模型。
例如,ViewModel可以使用User來更改地址:

user.ChangeAdress(new Adress("3 route de tartampion", "6900", "Lyon", "France"));

使用DDD澄清MVVM

如果我需要幾個模型怎麼辦?
DDD的另一種戰術模式可以幫助我們:領域服務,是我們管理域模型之間互動的地方。如果我們找不到更好的地方來為指定的用例提供業務邏輯,我們就會使用它。我們的ViewModel將操縱操作域模型的領域服務。需要多個模型的典型用例是驗證。
例如,ViewModel可以使用購買服務來驗證命令:
_buyingService.Validate(/*products to buy*/, /*current user*/)

使用DDD澄清MVVM

如果我不瞭解/關心DDD怎麼辦?
只需用Model替換DomainModel這個詞,用BusinessService替換DomainService。將SRP應用於設計類。
例如在C#中,Model不應該是INotifyPropertyChanged,它是一個UI關注點。ViewModel負責在屬性更改時通知View。
同樣的想法,ViewModel不應該嵌入業務邏輯,因為它已經負責UI行為。 簡單設計的簡單規則 

使用DDD澄清MVVM

  • View有責任向使用者顯示內容。我們不希望這裡有任何行為。
  • ViewModel有責任表示View的行為。我們談論的是UI行為,而不是業務行為。
  • 模型有責任封裝業務邏輯,而不關心它的顯示方式。這是我們放置業務行為的地方。
  • 如果涉及多個模型以滿足業務需求,則業務服務有責任封裝給定用例的業務邏輯。

使用DDD澄清MVVM

Github上給出一個簡單的例子

相關文章