DDD Modeling of value object and entities and dictionary types
Asked Answered
G

2

7

I wanted to bring my question to the bigger audience as we already discussed for some time in our company and cannot find an answer.

Let us suppose we have Transaction object which is aggregate root. Inside Transaction we have Money which is value object.

class Transaction {
    private Money money;
    // other stuff
}

and

class Money {
    private BigDecimal amount;
    private String currency;
}

Such Transaction can be persisted (we use hibernate) to db into simple table transaction

+-----------------+
| transaction     |
+-----------------+
|id : bigint      |
|amount: decimal  |
|currency: varchar|
|other...         |
+-----------------+

And everything would be great but... customer requires us to have currency table in database (we call them dictionary tables) and every table (including transaction) that have money need to point to the currency table:

+-----------------+           +-----------------+
| transaction     |           |curency          |
+-----------------+           +-----------------+
|id : bigint      |     +---> | id: bigint      |
|amount: decimal  |     |     | code: varchar   |
|curr_id: bigint  | ----+     | name: varchar   |
|other...         |           +-----------------+
+-----------------+

So from now on, Money object should look like this:

class Money {
    private BigDecimal amount;
    private Currency currency;
}

And from now we cannot call it value object :( or can we? It also complicates the way we are persisting the object as we cannot use hibernate embedable any more as we need to write our own custom type enter link description here. For sure we are not the first one facing this problems as dictionary types are popular in use, question is, how to treat them in scope of ddd modeling.

We will face similar problem when dealing with adresses. So, we know we have dictionaries like Country and FederalState (which are hierarchical). And we also know that many object in our application (e.g. Institution) have thei own adresses but also have connection to FederalState. So in simpe case we would have:

class Institution {
    Address address;
    // ...
}

where

class Address {
    String street;
    String houseNo;
    // etc..
    String federalState;
    String country;
}

But we need it to have relation to fedral state table, therefore Address will look like:

class Address {
    String street;
    String houseNo;
    // etc..
    FederalState federalState;
}

so we face again the same problem, Address is not value object from now on. We know how to do it technically but what is the right approach from the perspective od ddd?

Geothermal answered 5/10, 2016 at 12:27 Comment(11)
"And from now we cannot call it value object :(" - why?Gley
@Gley because, now that it has its own table, it gained a higher status and it may feel offended?Germinal
I can't see a Money table at that point in your question. Besides, deciding if an object is a Value Object or not has little to do with database tables.Gley
@Gley I think we want to stick to the definition where values object is just a named set of values (with some business reason) that can exist only in the context of identifiable entity or domain root. Maybe we understand it wrong but When we have currency as entity/dictionary it can change without value object noticing (which is of course wrong, but still) as value object holds reference to currency not value of currency.Geothermal
@siny "it can change without value object noticing (which is of course wrong, but still)" why is it wrong? For example, today's Beijing is yesterday's Pekin - a change in the name doesn't change the reality of the city. Same goes for ECU to EURO in the case of currencies.Germinal
@siny Adrian is right. Your problem is more with the true nature of Currency and FederalState than Money and Address.Gley
@Gley not only the "nature at any instant" but also in respect with the "needs to track evolution" - if changes in its attributes are significant enough to be tracked in their evolution, then for sure we are speaking about an "entity" rather than a "value".Germinal
I can see you point and i think your right. Thanks.Geothermal
In most of the cases our dictionaries are static and appendable if necessery. Therefore we can as you say treat them as a part of value objects.Geothermal
You may very well have a value object in your model that is an entity from the persistence-world's perspective and that is fine, as long as it stays a value in the model. Not all value objects have to be embeddables, otherwise you could never model a collection of values efficiently in a relational DB. Now, in your Currency - FederalState example, as long as Currency only references the ID of the state you are fine.Sergu
I have tried to put your advices into practice. If enyone is interested here is example of persisted dictionary values as a part of value objects: github.com/dsinczak/dictionary-persistanceGeothermal
G
1

"what is the right approach from the perspective od ddd"

First of all, using dictionary entities is not wrong. Be it only for the reasons that, unlike a string value, using a relation to a dictionary entity:

  1. avoids typos (more robust)
  2. allows managing the set of "values" without modification in the code - you simply load the dictionary from the storage and populate a drop-down instead of defining, say, an Enum in the code (more flexible).

Letting aside the two above, business requirements may impose this design. E.g. for the Currency case: when expressed as an entity allows the definition of the Exchange Rate relation, which in itself may be subject to an 'auditable record/history' approach for storing the evolution of the exc.rate over time.
Having a State dictionary is a good base for (possible future) extensions handling different sale tax policies, or legislative restrictions (product/service not allowed in some states - see 'medicinal' weeds and what not).

Germinal answered 5/10, 2016 at 13:6 Comment(0)
C
1

There is a good post https://enterprisecraftsmanship.com/posts/nesting-value-object-inside-entity/

Curency in your example are clearly value objects. You can create an wrapper Entity CurencyInTransaction on Value Object Currency and put business logic in Currency.

Chronograph answered 9/4, 2022 at 23:35 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Yellow

© 2022 - 2024 — McMap. All rights reserved.