Having Separate Domain Model and Persistence Model in DDD - c#

I have been reading about domain driven design and how to implement it while using code first approach for generating a database. From what I've read and researched there are two opinions around this subject:
Have 1 class that serves both as a domain model and a persistence model
Have 2 different classes, one implementing the domain logic and one used for a code-first approach
Now I know opinion 1) is said to simplify small solutions that do not have many differences between the domain and persistence models but I think it breaks the single responsibility principle and by that introduces a lot of issues when an ORM's conventions interfere with DDD.
What is a surprise to me is there are numerous code examples of how to implement opinion 1). But a haven't found a single example of how to implement opinion 2) and how to map the 2 objects. (Probably there are such examples but I failed to find a C# one)
So I tried to implement an example on my own but I am not sure if that's a good way to do it.
Let's say I have a ticketing system and tickets have expiration date. My domain model will look like this:
/// <summary>
/// Domain Model
/// </summary>
public class TicketEntity
{
public int Id { get; private set; }
public decimal Cost { get; private set; }
public DateTime ExpiryDate { get; private set; }
public TicketEntity(int id, decimal cost, DateTime expiryDate)
{
this.Id = id;
this.Cost = cost;
this.ExpiryDate = expiryDate;
}
public bool IsTicketExpired()
{
if (DateTime.Now > this.ExpiryDate)
{
return true;
}
else
{
return false;
}
}
}
The persistence model using Entity Framework as ORM will look almost the same but as the solution grows this might not be the case
/// <summary>
/// ORM code first Persistence Model
/// </summary>
public class Ticket
{
[Key]
public int Id { get; set; }
public decimal Cost { get; set; }
public DateTime ExpiryDate { get; set; }
}
Everything looking great so far. Now what I am not sure about is which is the best place to get a Ticket persistence model from the repository and how to map it to the TicketEntity domain model
I have done this in an application/service layer.
public class ApplicationService
{
private ITicketsRepository ticketsRepository;
public ApplicationService(ITicketsRepository ticketsRepository)
{
this.ticketsRepository = ticketsRepository;
}
public bool IsTicketExpired(int ticketId)
{
Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
TicketEntity domainModel = new TicketEntity(
persistanceModel.Id,
persistanceModel.Cost,
persistanceModel.ExpiryDate);
return domainModel.IsTicketExpired();
}
}
My questions are:
Are there any reasons opinion 1) would be preferred to opinion 2) other than speeding up development and reusing code.
Are there any issues in my approach of mapping the models? Is there something I missed that would bring up issues when a solution grows?

Are there any reasons opinion 1) would be preferred to opinion 2) other than speeding up development and reusing code.
Option 1 is just because of pure laziness and imagined increased development speed. It's true that those applications will get version 1.0 built faster. But when those developers reach version 3.0 of the application, they do not think it's so fun to maintain the application due to all compromises that they have had to do in the domain model due to the ORM mapper.
Are there any issues in my approach of mapping the models? Is there something I missed that would bring up issues when a solution grows?
Yes. The repository should be responsible of hiding the persistence mechanism. It's API should only work with domain entities and not persistence entities.
The repository is responsible of doing conversions to/from domain entities (to be able to persist them). A fetch method typically uses ADO.NET or an ORM like Entity Framework to load the database object/entity. Then convert it to the correct business entity and finally return it.
Otherwise you would force every service to have knowledge about persistence AND working with your domain model, thus having two responsibilities.
If you work with application services per the DDD definition you will probably want to look at the Command/Query separation pattern which can be a replacement of the application services. The code gets cleaner and you also get a much more lightweight API wrapping your domain model.

I got into this dilemma this year in a big project I was working at and it was a really tough decision to make... I would like to talk about this topic during hours, but I'll resume my thoughts for you:
1) Persistence and Domain model as the same thing
If you are in a new project with a database designed from zero for it I would probablly suggest this option. Yes, the domain and your knowledge about it will change constantly and this will demand refactoring that will affect your database, but I think in most cases it's worth it.
With Entity Framework as your ORM you can almost keep your domain models entirely free of ORM concerns using fluent mappings.
Good parts:
Fast, easy, beautiful (if the database is designed for that problem)
Bad parts:
Maybe the developers starts to think twice before to do a change/refactoring in the domain fearing that it will affect the database. This fear is not good for the domain.
If the domain starts to diverge too much from the database you will face some difficulties to maintain the domain in harmony with the ORM. The closer to the domain the harder to configure the ORM. The closer to the ORM the dirtier the domain gets.
2) Persistence and Domain model as two separated things
It will get you free to do whatever you want with your domain. No fear of refactorings, no limitations provinients from ORM and database. I would recomend this approach for systems that deal with a legacy or bad designed database, something that will probably end messing up your domain.
Good parts:
Completely free to refactor the domain
It'll get easy to dig into another topics of DDD like Bounded Context.
Bad parts:
More efforts with data conversions between the layers. Development time (maybe also runtime) will get slower.
But the principal and, believe me, what will hurt more: You will lose the main beneffits of using an ORM! Like tracking changes. Maybe you will end up using frameworks like GraphDiff or even abandon ORM's and go to the pure ADO.NET.
Are there any issues in my approach of mapping the models?
I agree with #jgauffin: "it's in the repository that the mapping should take place". This way your Persistence models will never get out from the Repository layer, in preference no one should see those entities (unless the repository itself).

Are there any reasons opinion 1) would be preferred to opinion 2)
other than speeding up development and reusing code.
I can see a big one (opinionated stuff ahead) : there is no "Persistence Model". All you've got is a relational model in your database, and a Domain object model. Mapping between the two is a set of actions, not data structures. What's more, this is precisely what ORM's are supposed to do.
Most ORM's now support what they should have provided from the start -- a way to declare these actions directly in code without touching your domain entities. Entity Framework's fluent configurations for instance allow you to do that.
You may be under the impression that no persistence model = violating SRP and trampling on DDD, because many implementations you can find out there do. But it doesn't have to be like that.

Related

How is Change Tracking an issue when separating the Domain Model and Persistence Model?

I was reading this question here: Having Separate Domain Model and Persistence Model in DDD
and specifically looking at this code:
public class ApplicationService
{
private ITicketsRepository ticketsRepository;
public ApplicationService(ITicketsRepository ticketsRepository)
{
this.ticketsRepository = ticketsRepository;
}
public bool IsTicketExpired(int ticketId)
{
Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
TicketEntity domainModel = new TicketEntity(
persistanceModel.Id,
persistanceModel.Cost,
persistanceModel.ExpiryDate);
return domainModel.IsTicketExpired();
}
}
This code means there is a separate Domain Model and Persistence Model. I am trying to understand what the limitations of using this approach are. All over the Internet I read about change tracking being an issue when using NHibernate, however I do not understand why. Change Tracking is dealt with after the domain model is mapped back to the persistence model. How is change tracking an issue? A practical example of how change tracking is an issue would help me.
Update
Please see the code below:
//Repository
public Ticket GetTicket(int ticketId)
{
return this.ticketsRepository.GetById(ticketId);
}
and I do this in the application service:
//Application Service
Ticket ticket = applicationService.GetTicket(1);
ticket.Cost = .....
TicketEntity ticketEntity = AutoMapper.Map<TicketEntity>(ticket);
ticketEntity.DomainMethod();
ticket = AutoMapper.Map<Ticket>(ticketEntity);
Q1) Are the benefits of an ORM lost in this code e.g. change tracking? Notice that the persistence object is returned from the repository and then is mapped to a domain object and then back to the same persistence object.
Q2) How does NHibernate track changes i.e. how does it know that Ticket(persistence object) is ticket 1 in the database. I guess it is not simply by the ID.
Change tracking is no issue. The mingling of Domain with Persistence is. The 'domain model' is mainly some data structure easily mapped to a table. In many domains, you might deal 99% with data structures with some rules attached. In those cases, your Domain model will look pretty much identical to Persistence model.
But going up a bit, at a more abstract level, the Domain Model models primarily business behaviour with state (data) being just an artifact. Further more, it looks at things from the business point of view (functionality).
Persistence model is about stored state i.e data structured in such a way that's easily retrievable. For domains with complex functionality that involves many concepts and their specific models and use case specific business rules, the resulted Model is quite different from the Persisted state.
How an ORM tracks changes is just an implementation detail that has nothing to do with DDD, however if the domain is rich enough, the simplistic CRUD solution and especially the mindset of domain model = state+behaviour a.k.a classes becomes an obstacle. With or without the ORM.
For the apps where the Domain = 98% Persistence Models, there's no problem, you can use whatever ORM you want.
Most of the details in answer from #MikeSW are correct; I only disagree with change tracking. My answer is more in terms of NHibernate than DDD.
Yes, change tracking will be an issue but it depends on how the ISession is managed. Further, not only change tracking, it will also affect other features of NHibernate like Session Level Cache, Lazy Loading etc.
Let us assume that ISession is managed on request level i.e. one ISession per request. And all activities mentioned below are part of one single request.
public TicketEntity GetTicket(int ticketId)
{
Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
TicketEntity domainModel = new TicketEntity(
persistanceModel.Id,
persistanceModel.Cost,
persistanceModel.ExpiryDate);
return domainModel;
}
public void SaveTicket(TicketEntity ticketEntity)
{
Ticket ticket = //Here, you have to map TicketEntity to Ticket
this.ticketsRepository.Save(ticket);
}
Now, following is the code somewhere in application in same request:
TicketEntity ticketEntity = applicationService.GetTicket(1);
ticketEntity.Cost = .....
.....
.....
applicationService.SaveTicket(ticketEntity);
NHibernate have ability to track changes happen in Ticket but that ability is not useful here. Ticket is lost while returning from GetTicket and new Ticket is created while SaveTicket. Change tracking feature of NHibernate is not used at all even though ISession was at request level and was able to see the changes happen.
Following code (which bypasses domain models) will track the changes properly though:
public Ticket GetTicket(int ticketId)
{
return this.ticketsRepository.GetById(ticketId);
}
Following is how you get and modify Ticket:
Ticket ticket = applicationService.GetTicket(1);
ticket.Cost = .....
.....
.....
Now, you do not call SaveTicket; instead you Flush the ISession somewhere in your application where you detect the EndOfRequest.
In this scenario, change tracking of NHibernate tracks the changes done to Ticket and flushes those automatically.
By translating persistence model to domain model, we bypass this ability of NHibernate because persistence model is never changed.
There are benefits and drawbacks of each approach. Refer this question.
Edit: (for your Update)
Q1): New code will take benefit of change tracking if same instance of persistence model is modified and visible to same ISession. It will also take benefit of Session Level Cache in that case. While mapping with AutoMapper, NHibernate will load referenced entities if any those may not be needed. This depends on each use-case though.
Q2): Actually this should be a different question being too broad to answer in this answer. Anyway, refer this.
On a side note, I would not recommand to separate domain model classes from persistence objects.
You might want to see what Vaughn Vernon did for his application on DOT.NET
He is the author of the famous book Implementing Domain Driven Design (IDDD). A must read that I recommand to any developer serious about DDD.
https://github.com/VaughnVernon/IDDD_Samples_NET/tree/master/iddd_identityaccess/Domain.Model/Identity

DTO vs. Domain Model, project organization

I have a project with a repository, a service layer, using EF6 and code-first POCOs. In the CustomerRepository, I am doing several projection queries that return objects.
I understand that the code-first POCO's are what would be considered "Domain Models", but if I were to do a projection query into a different model, what is that model considered? An example of this would be the CustomerOrderStats. Is that still a Domain Model, or should that be considered a DTO model?
Example
Object returned from Repository:
public class CustomerOrderStats
{
public string Name { get; set; }
public int Count { get; set; }
}
Query in the Repository
public CustomerOrderStats GetCustomerOrderStats(Guid customerGuid)
{
return customers
.Where(c => c.Guid == customerGuid)
.Select(new CustomerOrderStats
{
Name = c.Name,
Count = c.Orders.Count()
};
}
It could be either one, really. The definition of a model vs. a DTO isn't really a matter of how you organize any given framework, but rather what that object represents in the domain. If it has rich functionality or business logic or is an active part of the actual business process, it's probably a model. If, on the other hand, it's just a container of properties to move values from one place to another, it's probably a DTO.
The key here is whether the object is an active part of the business process. And a good rule of thumb here is often the name of the object.
Is it a name that non-technical business team members understand?
Is it a term they use to describe what the business does? (Even a very small part of the business)
Does it carry a meaning in the industry in general?
A DTO is generally something that exists for purely technical reasons. Component A needs to send data to Component B, but that operation is a technical one and not a business one. Data just needs to be, well, transferred. As a piece of the system, it's essentially built "from the bottom up" because it satisfies a low-level technical need.
A model describes a part of the business. It could be an element on a chart which defines the business process in non-technical terms, or an encapsulation of a business concept. As a piece of the system, it's essentially built "from the top down" because it is described generally by the business and then implemented specifically to meet that need.

Business logic integrated into entity framework

I've read some of the articles on BL, but the methodology seems counter intuitive to me. It seems to break up normal OOP principles. Here's an very simplified example: A client table contains the birthdate and gender of each client. A life expectancy table contains the clientId, age, and probability of survivorship to that age.
Wouldn't basic OOP principles call for methods to be integrated into the entity? E.g. the calculateSPTable() method in the client class.
class client {
int clientId;
int age;
bool male;
list<surviveProb> lifeExpectancy;
void calculateLifeExpectancy(); // calculates lifeExpectancy
}
class surviveProb {
int surviveProbId;
int clientId;
int age;
double probability;
}
Yet the methodologies today seem to suggest such operations must be in a separate layer and a separate class. Methods operating on entities should not be included in the entity framework entities. This seems counter intuitive. I really want to put methods into EF entities. Is this going to lead to problems? What am I missing here?
After some research I now use some patterns that I think are good for maintenance porpoises and understanding the application.
Let's say you want to register an account.
In the controller, I would have an AddAccountViewModel that only exposes the minimum properties to a user. No worries about him injecting something bad in an unexpected property. Now, using dependency injection, I would call a Facade. Let's say _accountsFacade.RegisterAccount and I would pass the View Model as a parameter.
Inside this method in the facade, I would do the mapping from the View Model to the Model and this Facade would be responsible for doing everything that needed to be done so the account could be created. In my opinion, here is where all the business logic goes. In this Facade, using dependency injection again, I use a unit of Work and add and edit entities to the context. _unitOfWork.AccountRepository.Add(account)
You see? Controllers only "route" the application, facades handle business, unit of work handles the context, the repository only communicates with the data base... And the model only expose properties.
This makes the mapping faster, as stated, and it separate concerns. Sometimes, the logic of adding an account may involve handling different objects that shouldn't be used inside the account object,
I hope you can understand what I want to explain, as my English is not so great.
Was it helpful?

Entity Framework classes vs. POCO

I have a general difference of opinion on an architectural design and even though stackoverflow should not be used to ask for opinions I would like to ask for pros and cons of both approaches that I will describe below:
Details:
- C# application
- SQL Server database
- Using Entity Framework
- And we need to decide what objects we are going to use to store our information and use all throughout the application
Scenario 1:
We will use the Entity Framework entities to pass all around through our application, for example the object should be used to store all information, we pass it around to the BL and eventually our WepApi will take this entity and return the value. No DTOs nor POCOs.
If the database schema changes, we update the entity and modify in all classes where it is used.
Scenario 2:
We create an intermediate class - call it a DTO or call it a POCO - to hold all information that is required by the application. There is an intermediate step of taking the information stored in the entity and populated into the POCO but we keep all EF code within the data access and not across all layers.
What are the pros and cons of each one?
I would use intermediate classes, i.e. POCO instead of EF entities.
The only advantage I see to directly use EF entities is that it's less code to write...
Advantages to use POCO instead:
You only expose the data your application actually needs
Basically, say you have some GetUsers business method. If you just want the list of users to populate a grid (i.e. you need their ID, name, first name for example), you could just write something like that:
public IEnumerable<SimpleUser> GetUsers()
{
return this.DbContext
.Users
.Select(z => new SimpleUser
{
ID = z.ID,
Name = z.Name,
FirstName = z.FirstName
})
.ToList();
}
It is crystal clear what your method actually returns.
Now imagine instead, it returned a full User entity with all the navigation properties and internal stuff you do not want to expose (such as the Password field)...
It really simplify the job of the person that consumes your services
It's even more obvious for Create like business methods. You certainly don't want to use a User entity as parameter, it would be awfully complicated for the consumers of your service to know what properties are actually required...
Imagine the following entity:
public class User
{
public long ID { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string Password { get; set; }
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Profile> Profiles { get; set; }
public virtual ICollection<UserEvent> Events { get; set; }
}
Which properties are required for you to consume the void Create(User entity); method?
ID: dunno, maybe it's generated maybe it's not
Name/FirstName: well those should be set
Password: is that a plain-text password, an hashed version? what is it?
IsDeleted/IsActive: should I activate the user myself? Is is done by the business method?
Profiles: hum... how do I affect a profile to a user?
Events: the hell is that??
It forces you to not use lazy loading
Yes, I hate this feature for multiple reasons. Some of them are:
extremely hard to use efficiently. I've seen too much times code that produces thousands of SQL request because the developers didn't know how to properly use lazy loading
extremely hard to manage exceptions. By allowing SQL requests to be executed at any time (i.e. when you lazy load), you delegate the role of managing database exceptions to the upper layer, i.e. the business layer or even the application. A bad habit.
Using POCO forces you to eager-load your entities, much better IMO.
About AutoMapper
AutoMapper is a tool that allows you to automagically convert Entities to POCOs and vice et versa. I do not like it either. See https://stackoverflow.com/a/32459232/870604
I have a counter-question: Why not both?
Consider any arbitrary MVC application. In the model and controller layer you'll generally want to use the EF objects. If you defined them using Code First, you've essentially defined how they are used in your application first and then designed your persistence layer to accurately save the changes you need in your application.
Now consider serving these objects to the View layer. The views may or may not reflect your objects, or an aggregation of your working objects. This often leads to POCOS/DTO's that captures whatever is needed in the view. Another scenario is when you want to publish objects in a web service. Many frameworks provide easy serialization on poco classes in which case you typically either need to 1) annotate your EF classes or 2) make DTO's.
Also be aware that any lazy loading you may have on your EF classes is lost when you use POCOS or if you close your context.

Entity Framework: storing as a list of complex type

I am kinda new with entity framework, I have the following scenario which I want to persist on DB with entity framework:
public class Period
{
public Period() { }
public DateTime From { get; set; }
public DateTime To { get; set; }
}
public class Class1
{
public Period Validity {get; set;}
}
public class Class2
{
public List<Period> Validities {get;set;}
}
I can persist Class1 configuring Period as a complex type, but then I cannot persist Class2.
I can persist Class2 configuring Period as an Entity, but then Class1 doesn't work when trying to add Class1.
And also, Period is not an entity, I don't want to treat it as an entity, I don't want to place an ID on Period, because my model has no sense with it. It was a struct and I has to make it become a class, already.
I would like to keep my existing model as it is now.
Is it there a workaround or something that can allow me to define mapping at a lower level?
Would it be possible with NHibernate 4? I am ready to switch my all persistence layer to nhibernate, if worth it!
Any hints?
If you try to squeeze your (non-anemic) domain model into an ORM, you will always have to make compromises. So this is usually not a good idea except for very simple applications.
Create a persistence model that consists of dead-simple, getter-setter-only classes without any logic. Make them in a way that fits EF well and use them to persist data. Now map your persistence model to your domain model an vice-versa.
This may seem like overkill, but is the only clean solution if you really want to apply DDD. Try to keep the two models close, so that the mapping is simple. Automapper is a good tool for this kind of model-to-model mapping.
You can't do exactly what you ask in NHibernate, but we know ORMs are all about tradeoffs. What do you really gain from Period having no ID ? Are you ever going to try to equate a Period from Class1 with a Period from Class2 using value equality ?
I usually care a lot more about the semantic benefit of VO's than their shape (no ID, comparison by value, etc.) In other words, I think making domain concepts explicit by grouping anonymous primitive values into well-named VO's is more important than not mistaking Entities for Value Objects or the other way around.
Thus I'm willing to sacrifice a bit of "purity" to still get the benefits of an ORM and not have to create an extra "data model" layer and the extra mapping that goes with it.
This doesn't mean you shouldn't try to find sense in Period being an Entity. Depending on your context, it may be possible. This article shows a solution where the VO is treated as a NHibernate Component when seen from its host object but as an Entity when created/edited. It might be a good middle ground option.

Categories