I have a WPF application where I want to apply MVVM for the presentation layer and DDD for the whole application. I am very confused with how I should apply the architecture. Can you give me some advises as it feels like I have completely messed up at the moment with the following design try:
I have 4 layers:
Presentation Layer
: This is where my WPF client application lies in.
Application Layer
: This is where I have my services that's supposed communicate with domain services for business rules and does CRUD. It works simply as an anti-corruption layer between Presentation
and Domain
layers.
Domain Layer
: This is where I have my aggregates, domain objects, and some services that reveals business rules, such as IsTooOld(Person person)
Infrastructure Layer
: This is the lowest layer, infrastructure lies in here, IRepository
, IEntity
etc..
Let's achieve a simple scenario with those DDD based layers: Have a Person object in a database, map it, CRUD the database, check persons' birthday and show it to the user.
I'll start with the WPF part. I create the following classes :
PersonView
: XAML view of the person
PersonViewModel
: ViewModel
that provides functionality for the PersonView
. PersonView
binds to this and this ViewModel
provides values from PersonModel
PersonModel
: This is the MVVM model that my PersonViewModel
is tightly coupled to.
This is good enough for the presentation layer. I now want to connect to the database to retrieve a person object to present it.
I must create:
PersonEntity
in Domain Layer
: An aggregate for the database entity, used for mappings with the database. It lies in Domain
layer.
Person
in Domain Layer
: This is the domain model of DDD. I'll put some logic here and I don't want to send around entity objects as DDD suggests.
Ok, I already have 3 person models that are pretty similar to each other. How about some more for data access and the services?
PersonService
in Application Layer
: When my presentation layer wants to communicate with this layer it needs to convert its PersonModel
(MVVM model) to Person
(domain model). This service in application layer then converts Person
(domain model) it into PersonEntity
(entity object) and does CRUD with the database. This service uses also another PersonService
(see below) in Domain layer to check/apply some business rules.
PersonService
in Domain Layer
: This layer works only with Person
domain object. It has business-related rules like bool IsTooOld(Person person)
.
To summarize, I've ended up with 7 classes for a simple scenario :
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
(the reason I've created this is that I can't use mapping for complex domain objects so I just put some data annotations here instead of mapping domain objects) This feels very very awkward. I'm not sure how I should re-structure it and benefit both domain driven design and MVVM patterns. I'm really stuck and I'm really looking forward for any advises or real life examples for applying both MVVM and domain driven design. I'm also open for any feedback for naming conventions or strategies for minimizing this much of work for simple operations.
I still have two concrete questions though :
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?
Should I merge my entity (database) models with domain models? Isn't it violation of DDD?
Update
Decisions I've taken:
PersonModel
)PersonEntity
added PersonMappings). Using persistence model is far more costly than simply mapping it. See : http://enterprisecraftsmanship.com/2016/04/05/having-the-domain-model-separate-from-the-persistence-model/ from Vladimir's answer.Finally it looks like this:
Presentation.WpfClient.View.PersonView
Presentation.WpfClient.ViewModel.PersonViewModel
Application.ApplicationServices.PersonService
(crud with some application related logic)Application.ApplicationServices.Mappings
(I have the repository abstractions and mappings here)Domain.Application.People.Person
(person object in it's bounded context, object is smart enough to handle domain logic)MVVM is the lingua franca of WPF developers because it is well suited to the WPF platform, and WPF was designed to make it easy to build applications using the MVVM pattern (amongst others).
Model–view–viewmodel (MVVM) is a software architectural pattern that separates the development of the graphical user interface from the development of the business logic or back-end logic. A DDD Entity is something that has identity and type in a business context.
MVVM (Model-View-ViewModel)It is based on the Model-view-controller pattern (MVC), and is targeted at modern UI development platforms (WPF and Silverlight) in which there is a UX developer who has different requirements than a more "traditional" developer.
This is way too many classes for a single concept.
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?
Yes, this is a preferable solution is many cases, especially if you don't use a communication mechanism like WCF. No violation here as MVVM doesn't impose a particular implementation of the model part.
Should I merge my entity (database) models with domain models? Isn't it violation of DDD?
Also, yes. Separating an entity into two (domain entity and "persistence" entity) usually leads to over-complication and anemic domain model. Here's more on this: Having the domain model separated from the persistence model.
Overall, I recommend you to look at this example. This looks like exactly what you need: a fully-fledged application written in WPF with the use of MVVM and DDD.
DDD is most beneficial in handling comlex business problem. In real project, it should be used in more flexible way deponding on how complex the domain is. I would like to use a multiple-strategies approach to adopt it.
For most of case which mostly is about CRUD data with few change in data structure. I would only use:
Presentation Layer : ViewModel
Service Layer: ViewModel<->Domin object
Domain Layer: Domain object same as Entity
For more complex Domain, where there are many important and reusable business logic on Domain object, then I would add core service (like your Domain.Application.Services.PersonService).
If there are also complex business logic needed for process data for easier mapping data between Presentation Layer and Domin Layer. I would add another model in Service Layer, similar as your Presentation.WpfClient.Model.PersonModel.
So basically the architecture you have righ now is ready for handling the case that your Person domain is very complex in your project. But I can't see it so far from your description.
To answer your questions:
You can remove the Presentation.WpfClient.Model.PersonModel in your MVVM models. It doesn't violate MVVM because in this case, your Domain Object is the Model, And you have Presentation.WpfClient.ViewModel.PersonViewModel as ViewModel.
You can merge Entity with Domain object if your Person domain doesn't have complex business logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With