I am struggling with persistence in Domain Driven Design. As far as I understand, domain model should never be persistent-aware. Let's say I am building a simple todo-list application. I have a task with following interface:
interface ITask
{
bool IsCompleted {get;}
string Description {get;}
void Complete();
void ChangeDescription(string description);
}
And the generic implementation should look like this:
class SimpleTask : ITask
{
public SimpleTask(string description)
{
ChangeDescription(description);
}
public bool IsCompleted { get; private set; }
public string Description { get; private set; }
public void Complete()
{
IsCompleted = true;
}
public void ChangeDescription(string description)
{
// some validation here
// ...
Description = description;
}
}
I want to have a description be necessary - because it's a business rule. So from this moment if I want to save this object via serializers I will fail because no parameterless constructor provided. And I shouldn't provide it because of no persistance-aware rule. If I model my task in a form of DTO\POCO I will end up with another problem - so called anemic model. Moreover, I don't want to provide setters to some properties.
So where is the solution to all of this? I can create a tightly-coupled saver that will know how to save and restore task state. But I can access only public properties and methods, what if internal logic of task will be complex and impossible to save\restore? Should I mark all fields in task internal and have a possibility to save inner state of object? Isn't it kinda code smell and violation of no persistence-aware rule?
How do you solve this?
From my understanding, Entity Framework is much less flexible than Hibernate so you will have to make a bit more compromises in the model. Vaughn Vernon, the author of Implementing Domain-Driven Design (IDDD) shows a great way of keeping self-encapsulated entities while making it easy to persist their state using Entity Framework.
If you can use the persistence store of your choice, you may as well use a different strategy that doesn't involve so much impedance mismatch (e.g. event sourcing).