Value objects in DDD - Why immutable?

二次信任 提交于 2019-11-29 20:26:07
Roger Johansson

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.

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.

David

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.

Aravind R. Yarram

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.

rhozet

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.

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;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!