在 WPF 应用程序中使用 MVVM 和 DDD 而无需太多 类
Using MVVM and DDD in WPF application without having too many classes
我有一个 WPF 应用程序,我想在其中为表示层应用 MVVM,为整个应用程序应用 DDD。我对应该如何应用该体系结构感到非常困惑。你能给我一些建议吗,因为感觉我现在已经完全搞砸了以下设计尝试:
我有4层:
Presentation Layer
:这是我的 WPF 客户端应用程序所在的位置。
Application Layer
:这是我的服务应该与业务规则的域服务通信并执行 CRUD 的地方。它只是作为 Presentation
和 Domain
层之间的反腐败层。
Domain Layer
:这是我的聚合、域对象和一些揭示业务规则的服务的地方,例如 IsTooOld(Person person)
Infrastructure Layer
: 这是最低层,基础设施就在这里,IRepository
, IEntity
等。 .
让我们用那些基于 DDD 的层实现一个简单的场景:在数据库中有一个 Person 对象,映射它,CRUD 数据库,检查人的生日并将其显示给用户。
表示层
我将从 WPF 部分开始。我创建以下 类 :
PersonView
: XAML 本人观点
PersonViewModel
: ViewModel
为 PersonView
提供功能。 PersonView
绑定到此,此 ViewModel
提供来自 PersonModel
的值
PersonModel
: 这是我的 PersonViewModel
紧耦合的 MVVM 模型。
领域层
这对于表示层来说已经足够好了。我现在想连接到数据库以检索一个人对象来呈现它。
我必须创建:
PersonEntity
in Domain Layer
:数据库实体的聚合,用于与数据库的映射。它位于Domain
层。
Person
in Domain Layer
:这是DDD的领域模型。我将在此处放置一些逻辑,我不想像 DDD 所建议的那样发送实体对象。
应用层
好的,我已经有 3 个非常相似的人物模型了。数据访问和服务的更多内容如何?
PersonService
in Application Layer
:当我的表示层想要与该层通信时,它需要转换它的 PersonModel
(MVVM 模型)到 Person
(领域模型)。然后应用层的这个服务将Person
(域模型)转换为PersonEntity
(实体对象)并与数据库进行增删改查。此服务还在域层中使用另一个 PersonService
(见下文)来 check/apply 一些业务规则。
PersonService
in Domain Layer
:该层仅适用于 Person
域对象。它具有与业务相关的规则,例如 bool IsTooOld(Person person)
.
总而言之,对于一个简单的场景,我最终得到了 7 类 :
Presentation.WpfClient.View.PersonView
Presentation.WpfClient.ViewModel.PersonViewModel
Presentation.WpfClient.Model.PersonModel
Application.ApplicationServices.PersonService
Domain.Application.Services.PersonService
Domain.Application.Models.Person
Domain.Application.DbEntities.PersonEntity
(我创建这个的原因是我不能对复杂的域对象使用映射,所以我只是在这里放一些数据注释而不是映射域对象)
这感觉非常非常别扭。我不确定我应该如何重新构建它并使域驱动设计和 MVVM 模式受益。我真的被困住了,我真的很期待任何关于应用 MVVM 和域驱动设计的建议或现实生活中的例子。我也欢迎任何关于命名约定或策略的反馈,以尽量减少简单操作的大量工作。
不过我还有两个具体问题:
我是否应该从表示层(MVVM 模型)中删除模型并仅使用领域层中的模型(DDD 模型)?这时候是不是违反了MVVM?
我应该将我的实体(数据库)模型与域模型合并吗?是不是违反了DDD?
更新
我做出的决定:
- 为 MVVM 的模型使用域模型(已删除
PersonModel
)
- 使用相同模型到数据库的外部映射(移除
PersonEntity
添加了 PersonMappings)。使用持久性模型比简单地映射它的成本要高得多。请参阅:http://enterprisecraftsmanship.com/2016/04/05/having-the-domain-model-separate-from-the-persistence-model/ 来自 Vladimir 的回答。
最后看起来像这样:
Presentation.WpfClient.View.PersonView
Presentation.WpfClient.ViewModel.PersonViewModel
Application.ApplicationServices.PersonService
(带有一些与应用程序相关的逻辑)
Application.ApplicationServices.Mappings
(我这里有存储库抽象和映射)
Domain.Application.People.Person
(person 对象在其有界上下文中,对象足够智能以处理领域逻辑)
关于你的第一个问题,使用领域层模型作为 MVVM 模型并不违反 MVVM (See definition of Model here)
有关该主题的更多详细信息和第二个问题的答案,请参阅:Entities VS Domain Models VS View Models
DDD 最有利于处理复杂的业务问题。在实际项目中,应该根据领域的复杂程度以更灵活的方式使用它。我想采用多种策略的方法来采用它。
对于大多数情况,主要是关于 CRUD 数据,数据结构几乎没有变化。我只会使用:
表示层:ViewModel
服务层:ViewModel<->Domin 对象
领域层:与实体相同的领域对象
对于更复杂的域,域对象上有许多重要且可重用的业务逻辑,那么我会添加核心服务(如您的Domain.Application.Services.PersonService)。
如果处理数据还需要复杂的业务逻辑,以便更容易地在表示层和域层之间映射数据。我会在服务层中添加另一个模型,类似于您的 Presentation.WpfClient.Model.PersonModel。
所以基本上你现在拥有的架构已经准备好处理你的项目中的 Person 域非常复杂的情况。但是根据你的描述我目前还看不到。
回答您的问题:
您可以删除 MVVM 模型中的 Presentation.WpfClient.Model.PersonModel。它不违反 MVVM,因为在这种情况下,您的域对象是模型,并且您有 Presentation.WpfClient.ViewModel.PersonViewModel 作为 ViewModel。
如果您的个人域没有复杂的业务逻辑,您可以将实体与域对象合并。
对于一个概念来说,类 太多了。
Should I remove models from presentation layer (MVVM models) and use only models from domain layer (DDD models) ? Isn't it violation of MVVM at this point?
是的,在很多情况下这是一个更可取的解决方案,尤其是当您不使用像 WCF 这样的通信机制时。这里没有违规,因为 MVVM 没有强加模型部分的特定实现。
Should I merge my entity (database) models with domain models? Isn't it violation of DDD?
还有,是的。将一个实体分成两个(领域实体和 "persistence" 实体)通常会导致过度复杂化和贫血的领域模型。更多相关信息:Having the domain model separated from the persistence model.
总体而言,我建议您查看 this 示例。这看起来正是您所需要的:使用 MVVM 和 DDD 以 WPF 编写的成熟应用程序。
我有一个 WPF 应用程序,我想在其中为表示层应用 MVVM,为整个应用程序应用 DDD。我对应该如何应用该体系结构感到非常困惑。你能给我一些建议吗,因为感觉我现在已经完全搞砸了以下设计尝试:
我有4层:
Presentation Layer
:这是我的 WPF 客户端应用程序所在的位置。Application Layer
:这是我的服务应该与业务规则的域服务通信并执行 CRUD 的地方。它只是作为Presentation
和Domain
层之间的反腐败层。Domain Layer
:这是我的聚合、域对象和一些揭示业务规则的服务的地方,例如IsTooOld(Person person)
Infrastructure Layer
: 这是最低层,基础设施就在这里,IRepository
,IEntity
等。 .
让我们用那些基于 DDD 的层实现一个简单的场景:在数据库中有一个 Person 对象,映射它,CRUD 数据库,检查人的生日并将其显示给用户。
表示层
我将从 WPF 部分开始。我创建以下 类 :
PersonView
: XAML 本人观点PersonViewModel
:ViewModel
为PersonView
提供功能。PersonView
绑定到此,此ViewModel
提供来自PersonModel
的值
PersonModel
: 这是我的PersonViewModel
紧耦合的 MVVM 模型。
领域层
这对于表示层来说已经足够好了。我现在想连接到数据库以检索一个人对象来呈现它。
我必须创建:
PersonEntity
inDomain Layer
:数据库实体的聚合,用于与数据库的映射。它位于Domain
层。Person
inDomain Layer
:这是DDD的领域模型。我将在此处放置一些逻辑,我不想像 DDD 所建议的那样发送实体对象。
应用层
好的,我已经有 3 个非常相似的人物模型了。数据访问和服务的更多内容如何?
PersonService
inApplication Layer
:当我的表示层想要与该层通信时,它需要转换它的PersonModel
(MVVM 模型)到Person
(领域模型)。然后应用层的这个服务将Person
(域模型)转换为PersonEntity
(实体对象)并与数据库进行增删改查。此服务还在域层中使用另一个PersonService
(见下文)来 check/apply 一些业务规则。PersonService
inDomain Layer
:该层仅适用于Person
域对象。它具有与业务相关的规则,例如bool IsTooOld(Person person)
.
总而言之,对于一个简单的场景,我最终得到了 7 类 :
Presentation.WpfClient.View.PersonView
Presentation.WpfClient.ViewModel.PersonViewModel
Presentation.WpfClient.Model.PersonModel
Application.ApplicationServices.PersonService
Domain.Application.Services.PersonService
Domain.Application.Models.Person
Domain.Application.DbEntities.PersonEntity
(我创建这个的原因是我不能对复杂的域对象使用映射,所以我只是在这里放一些数据注释而不是映射域对象)
这感觉非常非常别扭。我不确定我应该如何重新构建它并使域驱动设计和 MVVM 模式受益。我真的被困住了,我真的很期待任何关于应用 MVVM 和域驱动设计的建议或现实生活中的例子。我也欢迎任何关于命名约定或策略的反馈,以尽量减少简单操作的大量工作。
不过我还有两个具体问题:
我是否应该从表示层(MVVM 模型)中删除模型并仅使用领域层中的模型(DDD 模型)?这时候是不是违反了MVVM?
我应该将我的实体(数据库)模型与域模型合并吗?是不是违反了DDD?
更新
我做出的决定:
- 为 MVVM 的模型使用域模型(已删除
PersonModel
) - 使用相同模型到数据库的外部映射(移除
PersonEntity
添加了 PersonMappings)。使用持久性模型比简单地映射它的成本要高得多。请参阅:http://enterprisecraftsmanship.com/2016/04/05/having-the-domain-model-separate-from-the-persistence-model/ 来自 Vladimir 的回答。
最后看起来像这样:
Presentation.WpfClient.View.PersonView
Presentation.WpfClient.ViewModel.PersonViewModel
Application.ApplicationServices.PersonService
(带有一些与应用程序相关的逻辑)Application.ApplicationServices.Mappings
(我这里有存储库抽象和映射)Domain.Application.People.Person
(person 对象在其有界上下文中,对象足够智能以处理领域逻辑)
关于你的第一个问题,使用领域层模型作为 MVVM 模型并不违反 MVVM (See definition of Model here)
有关该主题的更多详细信息和第二个问题的答案,请参阅:Entities VS Domain Models VS View Models
DDD 最有利于处理复杂的业务问题。在实际项目中,应该根据领域的复杂程度以更灵活的方式使用它。我想采用多种策略的方法来采用它。
对于大多数情况,主要是关于 CRUD 数据,数据结构几乎没有变化。我只会使用:
表示层:ViewModel
服务层:ViewModel<->Domin 对象
领域层:与实体相同的领域对象对于更复杂的域,域对象上有许多重要且可重用的业务逻辑,那么我会添加核心服务(如您的Domain.Application.Services.PersonService)。
如果处理数据还需要复杂的业务逻辑,以便更容易地在表示层和域层之间映射数据。我会在服务层中添加另一个模型,类似于您的 Presentation.WpfClient.Model.PersonModel。
所以基本上你现在拥有的架构已经准备好处理你的项目中的 Person 域非常复杂的情况。但是根据你的描述我目前还看不到。
回答您的问题:
您可以删除 MVVM 模型中的 Presentation.WpfClient.Model.PersonModel。它不违反 MVVM,因为在这种情况下,您的域对象是模型,并且您有 Presentation.WpfClient.ViewModel.PersonViewModel 作为 ViewModel。
如果您的个人域没有复杂的业务逻辑,您可以将实体与域对象合并。
对于一个概念来说,类 太多了。
Should I remove models from presentation layer (MVVM models) and use only models from domain layer (DDD models) ? Isn't it violation of MVVM at this point?
是的,在很多情况下这是一个更可取的解决方案,尤其是当您不使用像 WCF 这样的通信机制时。这里没有违规,因为 MVVM 没有强加模型部分的特定实现。
Should I merge my entity (database) models with domain models? Isn't it violation of DDD?
还有,是的。将一个实体分成两个(领域实体和 "persistence" 实体)通常会导致过度复杂化和贫血的领域模型。更多相关信息:Having the domain model separated from the persistence model.
总体而言,我建议您查看 this 示例。这看起来正是您所需要的:使用 MVVM 和 DDD 以 WPF 编写的成熟应用程序。