Question

Lets suppose there's a database schema defined like this:

Person.mail_address_key ----- Address.address_key
Person.billing_address_key ----- Address.address_key

A Person has a mailing address and a billing address. As a denormalization technique, we create a separate Address table. Most of the time the mail_address_key and the billing_address_key of a single Person will be the same value (ie: their mailing and billing address key will be the same).

In my database the Address has an identity (the address key). But, in my domain model, I don't see a compelling reason for the Address to be an Entity, I'd like it to be a Value Object.

  1. In DDD, is this an option? Or are Value Objects usually a group of columns (as opposed to a table)? I'm kind of playing the devil's advocate here, because I don't think the database should dictate the domain model structure, but just making sure.
  2. If so, where/when/how does the address lose its database identity so it can be used as a Value Object in the Domain Layer? Or, am I supposed to keep the database identifier in the Value Object?
  3. When the model needs to be persisted in the database, what's the process? Am I supposed to go through a process of a) Find an address by these fields, b) if it doesn't exist, create a new one c) if it does, update the fields?
Was it helpful?

Solution

In DDD, is this an option? Or are Value Objects usually a group of columns (as opposed to a table)? I'm kind of playing the devil's advocate here, because I don't think the database should dictate the domain model structure, but just making sure.

The database should not dictate the domain model structure so you're correct on that. Value objects can be stored in the database as either a column or table depending on the type of data the value object is supposed to carry.

If so, where/when/how does the address lose its database identity so it can be used as a Value Object in the Domain Layer? Or, am I supposed to keep the database identifier in the Value Object?

Your domain code should not be riddled with properties that are for other concerns like persistence since they should be completely persistence ignorant. You should really focus on your aggregate root. You must have some way of identifying your aggregate root when you save it back to the database so, at that point, you would just need to check the Person table record (I'm assuming Person is your aggregate root) and see if there is a value in the MailingAddressID or BillingAddressID field. At that point, you can decide whether to create new addresses and change the links to point to the new addresses or overwrite the addresses that are already linked.

When the model needs to be persisted in the database, what's the process? Am I supposed to go through a process of a) Find an address by these fields, b) if it doesn't exist, create a new one c) if it does, update the fields?

As I somewhat explained in the above answer, you should hydrate and de-hydrate your object graph based on your aggregate root. Therefore, when your repository gets your aggregate root from the database, it will also hydrate all of the necessary entities and value objects under your aggregate root that are associated with your aggregate root in the database. The same is true when you go to save the aggregate root back to the database. Your repository should be able to handle your entire object graph under the aggregate root.

OTHER TIPS

DDD does not enforce DB schema at all. The value object may be implemented as a group of columns, db entity (your third solution) or simply in a denormalized form if you can use document-oriented database for instance. It depends on different circumstances what is the best option to go with.

Keep in mind that DB is only a tool for persisting your domain state. It should not force any design decision. If for some reason you have to use identity for your value object's representation in DB, do so, but do not leak this implementation detail into the domain itself. Create a wrapper/extend domain classes/whatever your framework allows and add the ID in completely separate, infrastructural class enabling the application/framework to persist the state.

I don't see any DDD's special requirements in this case, you can model mailing and billing addresses as person's properties and still store them in a separate table, for example:

Person
+ MailingAddress : Address
+ BillingAddress : Address

or

Person
+ MailingAddressID
+ MailingAddress : Address
+ BillingAddressID
+ BillingAddress : Address
Licensed under: CC-BY-SA with attribution
scroll top