Mark Needham

Thoughts on Software Development

Value objects: Immutability and Equality

with 13 comments

A couple of weeks ago I was working on some code where I wanted to create an object composed of the attributes of several other objects.

The object that I wanted to construct was a read only object so it seemed to make sense to make it a value object. The object would be immutable and once created none of the attributes of the object would change.

This was my first attempt at writing the code for this object:

public class MyValueObject
{
    private readonly string otherValue;
    private readonly SomeMutableEntity someMutableEntity;
 
    public MyValueObject(SomeMutableEntity someMutableEntity, string otherValue)
    {
        this.someMutableEntity = someMutableEntity;
        this.otherValue = otherValue;
    }
 
    public string SomeValue { get { return someMutableEntity.SomeValue; } }
 
    public int SomeOtherValue {get { return someMutableEntity.SomeOtherValue; }}
 
    public string OtherValue { get { return otherValue; } }
 
    public bool Equals(MyValueObject obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        return Equals(obj.OtherValue, OtherValue) && Equals(obj.SomeOtherValue, SomeOtherValue) && Equals(obj.SomeValue, SomeValue);
    }
 
    public override bool Equals(object obj)
    {
		// other equals stuff here
    }
}

It wasn’t immediately obvious to me what the problem was with this solution but it felt really weird to be making use of properties in the equals method.

After discussing this strangeness with Dave he pointed out that ‘MyValueObject’ is not immutable because although the reference to ‘SomeMutableEntity’ inside the object cannot be changed the object itself had lots of setters and could therefore be changed from outside this class.

There are two ways to get around this problem:

  1. We still inject ‘SomeMutableEntity’ but we extract the values from it in the constructor and don’t keep a reference to it.
  2. The client that creates ‘MyValueObject’ constructs the object with the appropriate values

The first solution would work but it feels really weird to pass in the whole object when we only need a small number of its attributes – it’s a case of stamp coupling.

It also seems quite misleading as an API because it suggests that ‘MyValueObject’ is made up of ‘SomeMutableEntity’ which isn’t the case.

My preferred solution is therefore to allow the client to construct ‘MyValueObject’ with all the parameters individually.

public class MyValueObject
{
    private readonly string otherValue;
    private readonly int someOtherValue;
    private readonly string someValue;
 
    public MyValueObject(string someValue, string otherValue, int someOtherValue)
    {
        this.someValue = someValue;
        this.otherValue = otherValue;
        this.someOtherValue = someOtherValue;
    }
 
    public string SomeValue { get { return someValue; } }
 
    public int SomeOtherValue { get { return someOtherValue; } }
 
    public string OtherValue { get { return otherValue; } }
}

The constructor becomes a bit more complicated but it now feels a bit more intuitive and ‘MyValueObject’ lives up to its role as a value object.

The equals method can now just compare equality on the fields of the object.

public class MyValueObject
{
	...
 
	public bool Equals(MyValueObject obj)
	{
	    if (ReferenceEquals(null, obj)) return false;
	    if (ReferenceEquals(this, obj)) return true;
	    return Equals(obj.otherValue, otherValue) && Equals(obj.someValue, someValue) && obj.someOtherValue == someOtherValue;
	}
}

A client might create this object like so:

var myValueObject = new MyValueObject(someMutableEntity.SomeValue, otherValue, someMutableEntity.SomeOtherValue);
Be Sociable, Share!

Written by Mark Needham

October 23rd, 2009 at 11:39 pm

  • Another approach that I use sometimes is to create a defensive copy of the object you’re wrapping, keeping a reference to it instead.

    I guess that’s a neat way of achieving this, specially if you need several attributes from your SomeMutableEntity.

  • So with the defensive copy would that mean that you make a copy of all the fields on the object and create a new one from those or would you make use of an in-built clone method or something?

  • A defensive copy would be a clone of the original – hopefully via some sort of ‘clone’ method. So you’d get the original as a constructor argument, and in the constructor you’d clone it and then save the clone.

    That way any external changes to the original will have no effect on the clone, and thus no affect on the ‘value’ object (and thus it’s immutability is preserved).

  • Note that this is _really_ commonly missed when dealing with collections. Although it’s still not perfect, I usually do this (in java):

    public Constructor(final List entities) {
    this.entities = new ArrayList(entities);
    }

    However, you often also have a getter for this list. So to be doubly sure nobody can modify the copy, I’d do:

    public Constructor(final List entities) {
    this.entities = Collections.unmodifiableList(new ArrayList(entities));
    }

  • Hi Mark,
    Yes you are correct. In Java I’d probably use the clone method like Chris mentioned.
    Also, his point about collections is very well taken as it can lead to a false impression of immutability.

  • Pingback: Reflective Perspective - Chris Alcock » The Morning Brew #462()

  • Chuck

    Mark – I liked your final solution. Red Alerts rang out when SomeMutableEntity was passed in. You touched on it: the Client doesn’t really know that you are not (internally) using SomeMutableEntity for some additional processing (oh, and what Dave said).

    Thanks for the post!

    C

  • @Chuck – yeah I guess if it had been called SomeMutableEntity in our code I probably wouldn’t have messed it up!

    Thought I’d use that name just to make it obvious why the first solution doesn’t make sense.

  • Pingback: DotNetShoutout()

  • Dave

    Your solution works fine if you only have a few parameters. If you want to add more parameters you change the signature of the method. This then causes you to either refactor (if all the parameters are required) or to overload the constructor, whereas if you just passed in the object changes would be minimal. Maybe a better solution is to have a static method on your SomeMutableEntity to return your value object. In the end the situation is going to dictate what you are going to do.

  • You cannot access the fields of obj to do the comparison, they are private.

    http://grabbagoft.blogspot.com/2007/06/generic-value-object-equality.html is a good generic implementation.

  • Ron

    Should MyValueObject also override Equals(object) and GetHashCode()? Imagine a case where your MyValueObject gets cast to ‘object’ and then Equals gets called on it or it gets placed in a Dictionary. You would want your custom Equals(MyValueObject) to be called, right?

    public override bool Equals(object obj)
    {
    if (obj is MyValueObject)
    return Equals((MyValueObject)obj);
    return false;
    }

    public override int GetHashCode()
    {
    return
    otherValue.GetHashCode() ^
    someValue.GetHashCode() ^
    someOtherValue.GetHashCode();
    }

  • @Ron – yeah sorry I should have mentioned that on the post.

    The implementation did override those as well but I didn’t show the code for that bit cause it’s quite verbose! Good spot!

    @alberto – we were able to access them because ‘obj’ refers to the class that we are currently in.

    Thanks for the link to the post, looks interesting.