45

I don't get why value objects in DDD should be immutable, nor do I see how this is easily done. (I'm focusing on C# and Entity Framework, if that matters.)

For example, let's consider the classic Address value object. If you needed to change "123 Main St" to "123 Main Street", why should I need to construct a whole new object instead of saying myCustomer.Address.AddressLine1 = "123 Main Street"? (Even if Entity Framework supported structs, this would still be a problem, wouldn't it?)

I understand (I think) the idea that value objects don't have an identity and are part of a domain object, but can someone explain why immutability is a Good Thing?


EDIT: My final question here really should be "Can someone explain why immutability is a Good Thing as applied to Value Objects?" Sorry for the confusion!


EDIT: To clairfy, I am not asking about CLR value types (vs reference types). I'm asking about the higher level DDD concept of Value Objects.

For example, here is a hack-ish way to implement immutable value types for Entity Framework: http://rogeralsing.com/2009/05/21/entity-framework-4-immutable-value-objects. Basically, he just makes all setters private. Why go through the trouble of doing this?

Hobbes
  • 451
  • 1
  • 4
  • 4
  • Value and reference types are generally intermixed as shown in your original question when speaking about Address (struct) value type and String (class) property value reference type. Is there any advantage to restrict your question to just value types? Can you open it up without diluting your intent? – John K Jan 03 '11 at 02:32
  • I'm not sure I follow. I'm not talking about CLR value types (structs, ints, etc) vs reference types (classes, etc). I'm talking about the DDD concept of Value Objects (as opposed to Entity Objects). – Hobbes Jan 03 '11 at 02:37
  • I scanned the question, saw C# and my mind jumped contexts. Thanks for the clarification. – John K Jan 03 '11 at 02:54
  • Value objects need not actually be immutable to avoid aliasing problems. Just pass them *by values* instead of *by reference* and you will be fine. See https://wiki.c2.com/?ValueObjectsCanBeMutable. – Géry Ogam Apr 07 '20 at 21:46

6 Answers6

62

Ignore all the crazy answers about thread safe etc, that has nothing to do with DDD. (I've yet to see a thread safe O/R mapper or other DDD friendly dal)

Imagine a value object for weights. lets say we have a KG value object.

sample (edited for clarity):

var kg75 = new Weight(75);
joe.Weight = kg75;
jimmy.Weight = kg75;

Now what would happen if we do:

jimmy.Weight.Value = 82;

That would change the weight of joe too, if we are still using the same object references that is. Note that we assigned an object representing 75kg to both joe and jimmy. When jimmy gains weight, it is not the kg75 object that has changed, it is jimmys weight that has changed, thus, we should create a new object representing 82 kg.

But what if we have a new session and load both joe and jimmy in a clean UoW?

 var joe = context.People.Where(p => p.Name = "joe").First();
 var jimmy = context.People.Where(p => p.Name = "jimmy").First();
 jimmy.Weight.Value = 82;

What would happen then? well, since EF4 in your case would load joe and jimmy and their weights without any identity , we would get two different weight objects and when we change jimmys weight , joe would still weigh the same as before.

So we would have two different behaviours for the same code. If the object references are still the same, then both joe and jimmy would get a new weight. If joe and jimmy are loaded in a clean uow, only one of them would be affected by the change.

And that would be quite incosistent imo.

By using immutable VO's, you would get the same behavior in both cases and you can still reuse object references for a smaller memory footprint when constructing object graphs.

Ankit Vijay
  • 3,752
  • 4
  • 30
  • 53
Roger Johansson
  • 22,764
  • 18
  • 97
  • 193
  • 7
    This argument is flawed. You are arguing from a technical perspective for something that is chosen for conceptual reasons. These concepts of Value Object and Entity exist outside of any specific implementation. – jason Jan 03 '11 at 08:23
  • 3
    It covers why we need immutable value objects, no matter if you use a specific technology or whatever, the weight 75kg is immutable no matter if you use EF4 or any other technology. if someones weight has changed, it is not the object representing 75kg that should change, you should assign a new weight to that person instead.. – Roger Johansson Jan 03 '11 at 08:37
  • 8
    Only throwing the theoretical aspects around will not quite show why you get in trouble if you ignore those. IMO, it is easier to get why the concepts exist if you can see why something would fail in a more concrete scenario. – Roger Johansson Jan 03 '11 at 08:45
  • +1 to @Roger. While the example link I've provided talks about the same thing, the explanation is not as explicit as you have mentioned – Aravind Yarram Jan 03 '11 at 15:32
  • 1
    @Roger Alsing: Your argument just says why mutability can sometimes get you in trouble. It doesn't argue why Value Objects should be immutable. The fact that you never mentioned the definition of Value Objects should be a clue that something is amiss. – jason Jan 03 '11 at 16:16
  • 2
    +1. Answered the question with a great example. Similar to Martin Fowler's explanation (http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable). – trebormf Jan 25 '11 at 21:35
  • Fundamentally, I think the issue is that a data holder will behave as a value if *either* it can never change, or if there only exists one reference to it, but it will behave as an entity if code which holds a reference to it can see it change outside the control of that code. To behave as values, data holders must either be unshared or immutable. Since value objects are supposed to be sharable, that implies they must be immutable. – supercat Apr 27 '14 at 21:47
  • In that context immutability is important in connection with the conception of ValueObjects.To wit cause both Jimmy and Joe rely on some idea of 75 kg and they are not interested in knowing is the 75kg object "unique" or not (ValueObjects areDefined byTheirAttributes, atTheContrast of entity ones). IOW they need to denote their weight of 75 kg and don't get any specific urge to have a relationship with the 75kg obj. So it can be confusable when the 75kg changes its essential being. I think it is even more notable than the fact we've set new Weight.Value with Jimmy's help, covering it from Joe. – Ilya Loskutov Aug 28 '19 at 10:55
  • Value objects need not actually be immutable to avoid aliasing problems. Just pass them *by values* instead of *by reference* and you will be fine. See https://wiki.c2.com/?ValueObjectsCanBeMutable. – Géry Ogam Apr 07 '20 at 21:45
  • thanks for such wonderful mental model and explanation !! can you (or point me to) similar kind of understanding for entity objects in context of DDD ? – rahulaga-msft Jun 20 '21 at 07:05
45

Why is 6 immutable?

Understand that, and you will understand why Value Objects should be immutable.

Edit: I'll lift our dialog into this answer now.

6 is immutable because 6's identity is determined by what it represents, namely the state of having six of something. You can't change that 6 represents that. Now, this is the fundamental concept of Value Objects. Their value is determined by their state. An Entity, however, is not determined by its state. A Customer can change their last name, or their address and still be the same Customer. This is why Value Objects should be immutable. Their state determines their identity; if their states changes, their identity should change.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 2
    I've seen examples like this, and they seem too simplistic. 6 is immutable because, like String, any operation you perform on it gives you a new object. 6+2 is not the number six that has been changed to eight; It's a new number. I get that, but I don't like the analogy. In the case of Address, the type is more complex and it is more difficult (and feels silly) to define operations on it that return a new type. For example, newAddress = oldAddress.ChangeLine1("123 Main Street")? – Hobbes Jan 03 '11 at 02:20
  • 1
    You're not thinking about this carefully enough. You _could_ create a type that mimics `int` that does modify the object when you invoke an instance-level method on it (call the class `Integer` and as an example, an instance-level method `Increase` that accepts a parameter of type `Integer`). Why don't we do that? Why do we model numbers as Value Objects? – jason Jan 03 '11 at 02:27
  • Gosh, I don't know. It wouldn't even occur to me to do otherwise =) Maybe give me a hint? – Hobbes Jan 03 '11 at 02:43
  • @Hobbes: What if `int` was mutable? What happens here? `6.Increase(1); Console.WriteLine(6);` Does that jive with your intuition as to what an `int` is, or is it completely contrary to your intuition as to what an `int` is? Should you really be able to change what `6` represents? – jason Jan 03 '11 at 02:53
  • 1
    Well, six is always six. Intuitively, Console.WriteLine(6) should always be "6". This example is straightforward enough, but I am having a hard time applying it back to the Address idea. I'm getting the sense from you that there is something dangerous about saying jason.Address.Line1 = "123 Main" and that it's better to say jason.Address = new Address(...). I still don't know why. – Hobbes Jan 03 '11 at 03:11
  • 9
    @Hobbes: Okay, but why is `6` always `6`? It's because `6`'s identity is determined by what it represents, namely the state of having six of something. You can't change that `6` represents that. Now, this is the fundamental concept of Value Objects. Their value is determined by their state. An Entity, however, is not determined by its state. A `Customer` can change their last name, or their address and still be the same `Customer`. This is why Value Objects should be immutable. Their state determines their identity; if their states changes, their identity should change. – jason Jan 03 '11 at 07:55
  • 2
    Last comment nails it perfectly. – Arnis Lapsa Jan 03 '11 at 08:13
  • 1
    @Hobbes: Suppose one says `jason.Address = fred.Address; jason.Address.Line1 = "123 Main";` What effect, if any, should that have on `fred.Address`? Should it leave `free.Address` unaffected? For some types like `Address`, a struct with exposed fields may offer the most logical semantics, with every variable or field of its type being "detached" from every other (and the fact that it's detached being readily apparent by the fact that it's a struct with exposed fields). – supercat Jun 18 '12 at 20:37
16

I'm very late to the party, but I'd been wondering about this myself. (Would appreciate any comments.)

I don't think it's been explicitly quoted here, but I think Evans' references to immutability were primarily in the context of sharing:

in order for an object to be shared safely, it must be immutable: it cannot be changed except by full replacement. (Evans p100)

There's also a sidebar in Evan's book called "Is Address a Value Object? Who's asking?".

If roommates each called to order electrical service [ie if two customers had the same address], the company would need to realize it. [So] Address is an Entity. (Evans p98)

In the example you gave, suppose the customer's Home and Business Address were both 123 Main Street. When you make the correction you describe, would both addresses change? If so, and if I'm reading Evans correctly, it sounds like you really have an Entity.

Taking a different example, suppose we had an object to represent a customer's full name:

public class FullName
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Customer
{
    public FullName Name { get; set; }
}

Without a value object, the following would fail:

[Test]
public void SomeTest() {
    var fullname = new FullName { FirstName = "Alice", LastName = "Jones" };
    var customer1 = new Customer { Name = fullname };
    var customer2 = new Customer { Name = fullname };

    // Customer 1 gets married.
    customer1.Name.LastName = "Smith";

    // Presumably Customer 2 shouldn't get their name changed.
    // However the following will fail.
    Assert.AreEqual("Jones", customer2.Name.LastName);
}

In terms of advantages generally, some are picked up at In DDD, what are the actual advantages of value objects?. Notably, you only have to validate a VO on creation. If you do that, then you know it's always valid.

Community
  • 1
  • 1
David
  • 2,038
  • 14
  • 11
  • Thank you for this. Evan's explanation is enlightening and your example really drives it home. – Justin J Stark Feb 10 '15 at 15:15
  • This is by far the simplest and best answer. It uses the example from the question, and shows why it would fail without being a VO. – Alisson Reinaldo Silva Dec 02 '15 at 19:00
  • why you did not had: `var fullname1 = new FullName { FirstName = "Alice", LastName = "Jones" };` and `var fullname2 = new FullName { FirstName = "Alice", LastName = "Jones" };` in first place to not get into this issue ? – rahulaga-msft Apr 10 '23 at 10:57
5

This might not be the complete answer. I am only answering your question on the advantages of Immutability.

  1. Because Immutable objects are thread safe. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.
  2. The references to the immutable objects can be easily shared or cached without having to copy or clone them as their state can not be changed ever after construction.
  3. For more advantages of Immutability you look here (LBushkin's answer) What's the advantage of a String being Immutable?

This is an example by Martin Fowler on why value objects should be Immutable.

Alright, while it is not mandatory to make VO as immutable (even DDD book doesn't say they have to be immutable), the main idea, in DDD, to make it a VO seems to be not to deal with life cycle complexities like that of an Entity. Look here for more details.

Community
  • 1
  • 1
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • Any argument that comes at this from a technical perspective is wrong. You never once used the fact that we are talking about Value Objects here. Your analogy to `string` is flawed since `string` is a reference type. Your argument is really about the benefits of immutable types, not why Value Objects should be immutable – jason Jan 03 '11 at 02:12
  • 1
    Isn't the Value Object implied here. Moreover the question asked is "can someone explain why immutability is a Good Thing". Now coming to the link I've provided; instead of copying the advantages verbatim, I specified the link which talks about advantages of Immutability. So can you enlighten me on why Address is not a reference type. – Aravind Yarram Jan 03 '11 at 02:19
  • Pangea: Good point. I asked "why immutability is a Good Thing," but what I really meant is "why is immutability a Good Thing" for value objects? I will edit my question to make it more clear. – Hobbes Jan 03 '11 at 02:21
  • I've read the c2.com link you posted. I think that they are not talking about Domain Driven Design? – Hobbes Jan 03 '11 at 03:38
  • @Hobbes - I've updated my answer. Look at the last paragraph. Hope this clears some stuff. – Aravind Yarram Jan 03 '11 at 04:26
  • I'd rephrases @Pangea 's argument as this: using immutable objects make it easier to write a correct program in most cases where they are practical (considering the PL and other technologies of your choice) and value object is a good match for them. And it's a valid point that it's not mandatory to make VO immutable. – Alexey Dec 04 '13 at 22:19
2

Value objects need to be immutable.

Immutable objects do indeed make life simpler in many cases. ... And they can make concurrent programming way safer and cleaner for more info

Let's consider value object to be mutable.

class Name{
string firstName,middleName,lastName
....
setters/getters
}

Let's say your original Name was Richard Thomas Cook

Now let's say you change only the firstName(to Martin) and lastName(to Bond), If it's not an immutable object, you will use the methods to mutate the state one by one. Chances of having name as Martin Thomas Cook in that Aggregate state before the final name of Martin Thomas Bond is never acceptable(also it gives a wrong thinking to the one who looks code later,leading to undesirable dominoes effect in further design).

Mutable value objects explicitly have to enforce integrity constraints for the changes given in 1 transaction,which is given free in Immutable objects. Hence it makes sense to make value objects immutable.

Community
  • 1
  • 1
rhozet
  • 542
  • 1
  • 6
  • 17
2

This has been asked a long time ago but I've decided to provide an answer with an example which I find straightforward and very simple to remember. Besides, SO works as a reference for many developers and I think anyone who bumps into this question could benefit from it.

Because they are defined by their attributes, value objects are treated as immutable.

A good example of a value object is money. It doesn't matter that you can't distinguish between the same five one dollar bills in your pocket. You don't care about the currency's identity -only about its value and what it represents. If somebody swapped a five dollar bill for one you have in your wallet, it would not change the fact that you still have five dollars.

So, for example, in C#, you define money as a immutable value object:

public class Money
{
    protected readonly decimal Value;

    public Money(decimal value)
    {
        Value = value;
    }

    public Money Add(Money money)
    {
        return new Money(Value + money.Value);
    }

    // ...


    // Equality (operators, Equals etc) overrides (here or in a Value Object Base class). 
    // For example:

    public override bool Equals(object obj)
    {
        return Equals(obj as Money);
    }

    public bool Equals(Money money)
    {
        if (money == null) return false;
        return money.Value == Value;
    }
}
dpant
  • 1,622
  • 19
  • 30