Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD and Persistence. Again

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?

like image 850
mrt Avatar asked Jun 29 '15 05:06

mrt


People also ask

What is persistence infrastructure?

Data persistence components provide access to the data hosted within the boundaries of a microservice (that is, a microservice's database). They contain the actual implementation of components such as repositories and Unit of Work classes, like custom Entity Framework (EF) DbContext objects.

What is the persistence layer c#?

The idea of the persistence layer is to encapsulate databases access routines. This allows applications to work with a set of objects (Data Objects) that read and save their state to a database; therefore applications do not need to have it in their source code SQL statements.

Are repositories part of the domain?

The repository is implemented in the domain layer, because it works with domain objects. But in the domain layer we should have no idea about any database nor any storage, so the repository is just an interface.

What is a repository DDD?

In DDD, a repository is an objcect that participates in the domain but really abstracts away storage and infrastructure details. Most systems have a persistent storage like a database for its fully functioning. Applying repositories happens by integrating and synchronizing with existing aggregate objects in the system.


2 Answers

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.

like image 188
plalx Avatar answered Sep 20 '22 16:09

plalx


If you have a look at the sample project from the author of DDD (http://dddsample.sourceforge.net/), you can see that Entities have a private empty-parameters constructor as a workaround for the Hibernate requirement for an object to be persisted.
So, a level of "dirtiness" in model's objects, I think, is allowed when it's due to technical limitations of the language or infrastructure.
Anyway, I'd suggest you to expose the creation of a ToDo entity via some factory methods (maybe of an Aggregate Root), so that you can enforce your business rule for object creation. That way, you give the client a sort of convention for operating with your model in the proper way.
You cannot avoid clients to create an invalid state model (think about reflection, byte code instrumentation, etc.), so what is really important is to design the proper way to use your model and instruct the client about it.

like image 28
Enrico Sanguin Avatar answered Sep 20 '22 16:09

Enrico Sanguin