Kurser i Domain-Driven Design - Våren 2012




Friday, August 28, 2009

One Man's Entity Is Another Man's Value Object

One activity that we tend to spend some time on when doing Domain-Driven Design is the characterization of our classes into Entities of Value Objects. Entities and Value Objects are two fundamental building blocks that we use to handle complexity and help us further deepen our understanding of the problem domain. Careful characterization can make our design simpler, yet more powerful.

Here are two things that I like to stress during this work:
1) It's not always obvious what type of building block a model item is.

Let the characterization process take time, do not be afraid to experiment. Try out a few different key scenarios, both by "modeling out loud" by expressing scenarios in the words of the Ubiquitous Language as conversations with other people on the team, and in code. Work hard to challenge your initial assumptions, refactor as needed. That said, if you have a choice, bias your design towards Value Objects. We favor Value Objects for their uninteresting life-cycle and immutability, we use them to push down complexity. Imagine if java.util.GregorianCalendar was immutable...

2) The characterization is context-dependent, i.e. one man's Entity is another man's Value Object.

Let's consider money, a popular choice when discussing Value Objects. Imagine I have a SEK 100 note and walk over to a person and ask her if she'd be willing to exchange my note for one of her SEK 100 notes. The person would most likely accept this proposal (after some initial suspiciousness, one can imagine). I get her note and she get's mine. From both our points of view, nothing really happened. I can still go down to the store and buy something priced at SEK 100. She can do the same. The value property of the note is what is important to us, not the particular note instance; as long as they have the same value, they are interchangeable. They are also immutable. When I get a note in my possession, it's value is already set. There is no way I can (legally) change the value written on the note. I pass it along as means of payment and I forget about it. As far as I am concerned it can be garbage collected when I no longer hold on to it.

However, if I walk over to a person and ask her if we can exchange VISA cards, odds are she won't agree. And we all know why. Our cards may be issued by the same bank, have the same shape and color, and both be VISA cards. But they also have a card number, they have an identity. The actual card instance does matter. Credit cards have a complex life-cycle tracked by this identity; they are issued, lost and cancelled, or stolen, or just expired. They are connected to an account, which may have a huge credit just waiting to be spent, or it may be overdrawn. We think twice before handing over the card to someone, because that someone can do things to our card that we don't want. Evil things. Things like (VisaCard) card.clone(), or card.charge(2 * amountAgreedUpon). In short, credit and debit cards are Entities and we need to handle them with care. Entities are high-maintenance. But can be oh so useful.

Now, if we scrutinize that SEK 100 note carefully, we will find a number, a serial numbers. So what is this? Notes do have an identity after all? Perhaps they are not Value Objects at all?! What is going on here? Well, I do not know this domain very well, but it is not that hard to imagine that there is someone somewhere that do care about tracking individual notes. Perhaps Sveriges Riksbank, Sweden's central bank, uses this information to track individual notes, as they enter them into circulation or destroy them when no longer in use. I bet there is a computer software system somewhere, in a different Bounded Context, where banknotes are Entities.

Read more about the Building Blocks of a Model-Driven Design in the DDD Pattern Summaries (.doc file).
Watch Dan Bergh Johnssons presentation The Power of Value from Øredev 2008.

Heldagsseminarium: Domain-Driven Design, 23 september 2009 i Stockholm

No comments: