11

I have an entity and I've realised that there is a group of properties that work together. So, I moved them to a value object (together with their behavior) and now I have a reference from my entity to this value object.

I've read "Domain Driven Design Quickly" (PDF) and I came across the following statement when explaining Value objects:

If Customer is an entity object, then one instance of this object, representing a specific bank client, cannot be reused for account operations corresponding to other clients. The outcome is that such an instance has to be created for every client. This can result in system performance degradation when dealing with thousands of instances.

But I'm still not clear exactly what this means. Is my new object a value object or should it be an entity? I am having trouble reasoning whether it should in fact be an entity. In other words, what questions should I ask in my domain to assure me that it should be a value object?

0

4 Answers 4

8

To expand on the answer by ques, a value object does not have a surrogate identity such as a customer number, but the object itself is its own natural identity.

Take an address for example. All addresses are unique, and the various components of an address (number, street name etc) make up the addresses identity. When you move house, you don't pick up your address, change the number on the door and take it with you, you get a new address. As such value objects don't change - they are immutable. However you could have 2 or more customers living at the same address, in which case the address value is reusable - it is not tied to a single customer entity.

3
  • Thanks Matt for replying. I am starting to understand what a value object is but my question was more to do with the paragraph I read in the pdf mentioned above. The paragraph talks mentions "cannot be reused for account operations" and "performance degradation". This is what confused me as I don't know what it is referring to. Can you help clear it up?
    – JD01
    Dec 19, 2011 at 11:15
  • 1
    The can not be reused part mens that you can not use one object for multiple purposes because each of them is an individual for itself. For each client in a bank you have to create his own account (you cant share this informations between more clients) the performance part means that if you have a lot of these "individuals" you are going to end up with a lot of them which first of all can fill up your memmory and secondly you will lose a lot of time for the creation of each of them. Dec 19, 2011 at 11:36
  • @Ivan: Thank you. When I first read it I kept thinking about my data model and did I kept thinking of value objects as reference object (i.e not immutable) which is something I should not do in DDD.
    – JD01
    Dec 19, 2011 at 12:43
12

Here is the best analogy that I've been able to "teach" to my co-workers when wanting to work on DDD with Value Objects.

Every time you think of a Value Object, think of DateTime object in .Net.

For example, when you have a DateTime in your object, and you persist that object, you are only saving a string representation of the date and time in question. It can also be formatted to satisfy certain locales (month-day or day-month for example).

Yet, the DateTime object is so sophisticated internally. They have multiple members to store different values (day, month, year, hour, minute, seconds, milliseconds) so that they can do operations like .AddDay(2) which basically takes the day field, adds a 2 to it, and returns a brand new DateTime object with the new addition. So, you really never modify the DateTime object. You create a new one every time you use one of their methods.

Same for your custom value objects... Say, CreditCard... let's look at an example.

We want to store credit card information for a user. In our domain, we don't need to keep track of the Creditcard. So, the first thing that we may be tempted to do is to create 4 fields.

string CreditCardNumber {get;set;}
string CreditCardExpiration {get;set;}
string CreditCardType {get;set;}
string CreditCardSecurityCode {get;set;}

Now say that we have these fields in our AggregareRoot/Entity. If we want to 'parse' our ExpirationDate to a meaningful DateTime object (07/18 to 07/01/2018) for validation purposes, now we need to add that logic to our AR/Entity. You may think... "that's ok" but it is not, because our AR/Entities should be focused on the problem that they solve, not validating credit card expiration dates. That's more ancillary work.

Imagine if DateTime didn't have all those functionalities of Date and Time manipulation and you need to implement all of that in your class, does it sound right? Of course not.

So, in our example, we create a CreditCard class

public class CreditCard: ValueObject

then we transfer all of those fields into this class (you can remove the CreditCard prefix). Now you have a lot of power in your hands. You can create as many validation methods as you want: checksum validation, expiration date validation, and parsing, actually validate that the credit card type matches its number sequence (Mastercard starts with 54 if I am not mistaken)... I mean, you can add SO many features to your CreditCard class without polluting your AR/Entity. You can create your own "format" to persist this info if you want. Say that you override your .ToString() method and format it as "MC 5474 3434 8383 4848 07/18". Or you can configure your ORM to map to the individual read-only properties for those values.

How do you use it effectively? Simple. Say that you have a PaymentMethod class that is an Aggregate Root. You want to keep track of that payment method because it will be used to make payments, so maybe you want to have a payment history linked to this class.

Inside your class, all you need to do is add a CreditCard value object...

public CreditCard BusinessCard {get;}

Now in one of the methods of your AR... say,

private void Enable()
{
    this.IsEnabled = BusinessCard.IsValid();
}

Do you see? I moved the logic of validating the card into the value object. And guess what? Can be reused!!! You can actually share value objects.

I hope this helps!

1
  • 1
    This is, by far, the best explanation I’ve seen of value objects. Thanks for addressing the “why” instead of just the “what”. The Uri class is another good example.
    – maembe
    May 18, 2020 at 3:52
3

The key property of a Value Object it that it has no identity. It is defined only by it's attributes, and any other instance with identical attribute values can be substituted.

Los Techies had a good explanation on their blog a while back, and it has been asked on StackOverflow.

0

Let's start with What is the value object? before I answer this question I will ask you a question first,

Which variable type would you use for representing the age of a person?

[ ] Integer
[ ] Boolean
[ ] String

The correct answer was none of the three. To represent the age of a person, you should use an Age type.

“Is an integer not enough?“ — you may ask. No.

An integer has different properties and operations that age hasn’t.

  • Does it make sense to add or subtract two ages? Maybe.
  • Does it make sense to multiply or divide two ages? Don’t think so.
  • Does it make sense to allow negative ages? Probably not.

!! How do you make sure that an integer variable representing an age is initialized with a valid value? You need to explicitly check before assigning it, in every assignation occurrence in your code. !!And how do you make sure that your integer value is not accidentally modified at a later time? You can’t unless you are using a language that allows for immutable variables and you declare yours as such.

So we could identify the value object as tyey are small objects, like money, strings, dates, or date ranges. Their equality is based on state, not on identity; two value objects are equal when they have the same value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.