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 betweenPresentationandDomainlayers.Domain Layer: This is where I have my aggregates, domain objects, and some services that reveals business rules, such asIsTooOld(Person person)Infrastructure Layer: This is the lowest layer, infrastructure lies in here,IRepository,IEntityetc..
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.
Presentation Layer
I'll start with the WPF part. I create the following classes :
PersonView: XAML view of the personPersonViewModel:ViewModelthat provides functionality for thePersonView.PersonViewbinds to this and thisViewModelprovides values fromPersonModelPersonModel: This is the MVVM model that myPersonViewModelis tightly coupled to.
Domain Layer
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:
PersonEntityinDomain Layer: An aggregate for the database entity, used for mappings with the database. It lies inDomainlayer.PersoninDomain 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.
Application Layer
Ok, I already have 3 person models that are pretty similar to each other. How about some more for data access and the services?
PersonServiceinApplication Layer: When my presentation layer wants to communicate with this layer it needs to convert itsPersonModel(MVVM model) toPerson(domain model). This service in application layer then convertsPerson(domain model) it intoPersonEntity(entity object) and does CRUD with the database. This service uses also anotherPersonService(see below) in Domain layer to check/apply some business rules.PersonServiceinDomain Layer: This layer works only withPersondomain object. It has business-related rules likebool IsTooOld(Person person).
To summarize, I've ended up with 7 classes for a simple scenario :
Presentation.WpfClient.View.PersonViewPresentation.WpfClient.ViewModel.PersonViewModelPresentation.WpfClient.Model.PersonModelApplication.ApplicationServices.PersonServiceDomain.Application.Services.PersonServiceDomain.Application.Models.PersonDomain.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:
- Use domain model for MVVM's model (removed
PersonModel) - Use external mappings for the same model to the database (removed
PersonEntityadded 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.PersonViewPresentation.WpfClient.ViewModel.PersonViewModelApplication.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)