Question

I have been working on a little project in DDD. I see everywhere that Value Objects are immutable, thus, you can't modify it. Only entities.

I am going to use the example everybody uses. Address. Let's say Address is a VO of the Customer entity (which is a root aggregate as well). If the user updates his Address, which is valid in any shopping cart scenario, then what am i supposed to do? I have to modify that VO address in order for me to persist it into the database. Meaning, this VO must have an identity somehow in order for me to identify it in the database. Unless NHibernate takes care of it using mapping, right. That's not the case with LinqToSql thou. Or I guess i have to create a new Aggregate where Address is an entity instead? Then almost having a copy of Address everywhere i need Address in my aggregates?

However. I still can't wrap the whole Entity/VO concept. Seems to me like everything that has a representation on the DB, even thou you use it as a VO in your Model, it's somehow an entity because in order for you to persist it, you need some sort of KEY to identify it in the database.

At the end of the day, all Value Objects's data come from a database (mostly). So i still can't understand how you must make them immutable in case of updates in that data.

After two months of intense reading, i find the whole DDD a huge contradiction issue. Read all those blogs and you will see what i am talking about. Unfortunately there is ZERO demo applications out there that you can use as a role model or guidance. They all are pretty much influenced by the developer's preferences. Then they end up attacking each other's blog. Overnight-DDD-Guru's blogs are really helping to the confusion of the whole community.

Thank you for stopping by. Looking forward for a constructive discussion.

Was it helpful?

Solution

I believe your confusion lies in the artificial coupling between database row identity and the notion of identity associated with an entity in DDD. They are certainly related because an entity will have a corresponding identity represented in the database as an identity column. However, just because something has an identity as a database row it doesn't mean that the object has identity in the DDD sense.

In you address example, the value comprising the address VO would typically be stored in the same row as the customer entity. In this way, the address is a value object because it isn't stored in a row of its own and has no identity. When you update an address, you alter the value of the address property on the customer entity, which in turn reflects in the database row.

There are cases where a value object would be stored in its own row. For example, in the stereotypical sales order model, an order is an entity (aggregate root) and line items are value objects. While line items are VOs, in the relational model, they are stored in their own table and may very well have primary keys. In the domain model however, the VOs are tied to the order entity and don't have identity outside of that entity.

OTHER TIPS

Actually, there's PLENTY of demos around, probably in every technology you imagine, starting with original DDDSample in Java. There are at least two ports of this sample to .NET: NDDD and DDDSample.Net.

As for VOs and persistence, if you think of a VO as an object wrapping few columns from a table representing an entity than it is easy (e.g. Money VO wrapping amount and currency). The problem starts when you want to normalize the data on SQL level and create a table for VOs (instead of embedding them in the entity tables). I don't know the good solution for the problem but fortunately it is not a good practice when implementing DDD with relational storage. Why? One of the most important principles is that aggregates should be as much independent of each other as possible. Sharing a VO class in object model is OK with this rule but sharing VO table in data storage is not, as this single table may become a locking bottleneck for example.

In short: when using SQL database to store domain model consider not normalizing the model between aggregates.

You can also try to have a look at such problems from the real world (or domain) point of view. Addresses rarely change. It's more common that the customer changes his address (he's moving to another flat for instance) that the address itself is changed.

Having this in mind an address has to be a value object.

Hey I see this is a really old question, but I am on my DDD quest and have had some similar queries.

The best route to a solution I have found with DDD is to forget about the DB and think about the model. So in the situation above, where you have a Customer and an Address VO and you want a list of Addresses for a customer, say in the scenario of an Ecommerce site where the customers has multiple shipping addresses to choose from. Well, in the true context of the domain model, those addresses are not just Address VOs, they are CustomerShippingAddress entities.

So, your CustomerShippingAddress entity has an identity, and it has an Address VO. Maybe it has some other stuff like IsDefault, and DateAdded etc

I would suggest you can only instantiate a CustomerShippingAddress from the Customer entity passing in an Address VO, and you get back an Aggregate root of the CustomerShippingAddress which holds an ID reference to the customer.

This way you maintain your AddressVO, but can reuse that VO in multiple scenarios.

When a customer selects an Address as the shipping address for an order, the AddressVO they choose would be applied to the Order aggregate. This means the shipping address on that order is locked in time to the Address VO at that time. The CustomerShippingAddress may be modified later, but the shipping addressVO would remain the same on the Order for ever.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top