DDD - How to store aggregates in NoSql databases
Asked Answered
V

4

10

A current project needs us to persist domain objects in a NoSQL database such as mongoDB. In many examples (incl. Eric Evans, Vaughn Vernon) the domain objects are serialized and persisted to the mongoDB directly.

We would like to avoid mixing the domain layer with persistence related inforamtion by not having any annotations in our domain objects. Also we are concerned about corrupting the persisted data by changing the domain object in the future.

We came to the conclusion that we need to have some kind of DTOs translating between the domain objects and the persisted data.

Did anyone of you come across a good solution for such a case?

Vidda answered 31/5, 2017 at 14:45 Comment(3)
I'm using reflection to map from mongo to PHP objectsNeille
Why don't you use an ORM with xml mapping?Neille
@ConstantinGALBENU why do you mention ORM, which is object-relational mapping, in the context of non-relational data? I am confused. Objects are serialised to BSON and stored as-is in any document database, including MongoDb.Collapse
B
4

Like you, I want business objects to have no dependency on any kind of specific repository. I solved it like this: That have your business object define its state objects and repository functions as interfaces. Your repository implementation can create an actual state object and inject that into your business object using the constructor.

There are a lot of advantages to this approach (such as having business objects for specific purposes), but you easily achieve complete (two-way) independence of your repository this way. Martin Fowler also hinted at this approach elsewhere.

I actually use the same pattern in my Angular / TypeScript projects. My read-api calls return DTO objects that get state objects injected as well and their properties map directly onto state objects.

These DTOs that end up as untyped javascript objects when they come from the api to the client (Angular) project are then in turn injected as state objects into TypeScript objects, injected in the constructor again and mapped by getters and setters. It works very cleanly and is well maintainable. I have an example on my GitHub (niwra) account (Software-Management repositories), but can expand here if anyone is interested.

MongoDB allows for very clean and Unit-Testable repository implementations, that returns strongly typed aggregates. The only thing I haven't solved cleanly yet is telling MongoDb about state objects for child-collections. Currently that is pretty 'static' still, but I'm sure I'll find some nice solution.

Baerl answered 6/6, 2017 at 15:51 Comment(0)
M
3

Yes. Your domain models should be ignorant of persistence. So you need a DTO or what I call data models (apart from the domain models and view models). Your data models will be map to the domain models before persisting to the database. This mapping is pretty common in insert and update operations. For read-only operations (reporting, etc) you can bypass the mapping from data models and to domain models. That will prevent loading the whole object graph of your domain models. This is widely applied in CQRS architecture patterns where read and write commands are separated.

Merrow answered 31/5, 2017 at 18:4 Comment(0)
C
3

You can store your domain objects as-is in document databases. Vaughn Vernon has posted an article The Ideal Domain-Driven Design Aggregate Store? about this, featuring PostgreSQL new (at that time) JSONB document-like storage.

Of course, you get a risk having your aggregates polluted by BsonX attributes, which you probably do not want. You can avoid this by using convention configuration but you will still need to think about serialisation and this can have an effect on the level of encapsulation.

Another pattern here is to use a separate state object, which is then held as a property inside the aggregate root (or regular entity). I would not call it a "DTO", since this is clearly your aggregate state. You are not transferring anything. Methods inside your aggregate can mutate the state or, even better, the state would be an immutable value object and new state is produced when you need to change the state.

In such case persistence would only care about the state object. You still might be unhappy to have MongoDb attributes on the state object properties and this is reasonable. Then, you would need to have an identical structure inside the persistence mechanism, so you can map properties on-to-one.

Collapse answered 2/6, 2017 at 20:48 Comment(0)
N
1

A current project needs us to persist domain objects in a NoSQL database such as mongoDB. In many examples (incl. Eric Evans, Vaughn Vernon) the domain objects are serialized and persisted to the mongoDB directly.

I can confirm you that MongoDB is a good choice for persisting DDD models. I use MongoDB as an Event store in my current project. You can use MongoDB even if you are not using Event sourcing, for example using an ODM (Object Document Mapper): you have a document for each Aggregate instance (this applies to any document based database, not only MongoDB) and you store nested entities and value objects as nested documents.

We would like to avoid mixing the domain layer with persistence related inforamtion by not having any annotations in our domain objects.

You can use xml mapping.

Also we are concerned about corrupting the persisted data by changing the domain object in the future.

For this you can use custom migration scripts. If you use Event sourcing then there are event versioning strategies.

We came to the conclusion that we need to have some kind of DTOs translating between the domain objects and the persisted data.

This is a bad conclusion.

If you use CQRS you won't need DTOs because the readmodels are enough.

Neille answered 1/6, 2017 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.