Pragmatism in the real world

Immutable entities

I’ve been thinking recently about using immutable objects for some of my model-layer entities. That is, an object that cannot be changed once it is created.

Immutable objects have a number of benefits including the fact that they are much easier to understand, simple to use and very easy to test. The main motivation for me is that an immutable object is very predictable as it’s state doesn’t change. This means that any calculated properties can be done once on creation. This is interesting as one application that I’m currently working on has a lot of calculated properties and it’s a source of bugs when one property changes and all the dependent calculations aren’t always done.

Immutable objects, as the name implies, cannot be changed. However, properties on our entities do need to change and we can’t simply call a set method to change a property. To change an immutable object, we have to create a new object with the new data and delete the old one.

This is clearly more overhead than using a setter method to change a property, but I’m wondering if it’s worth the cost for the simplifications elsewhere.

In traditional thinking about object orientation and the domain layer, entity objects have an identity that persists over time which is usually modelled as an id of some sort. The other values within the object change over time. For example a Customer object’s title may change (e.g. received a doctorate), but it’s still the same customer. As a result our Customer model entity is expected to be mutable. This is especially true if you are using an ORM as the object is coupled to the database row.

I think there’s a clear set of entity objects in some of the applications that I write where my life would be simpler if they were immutable. This is especially true of fairly complex business applications with lots of interacting entities that are used to generate reports and analysis.

To me, this is an area worth exploring. Thoughts?

7 thoughts on “Immutable entities

  1. Actually you've invented ValueObjects which is pretty important in the DDD world. The difference between Entities and VOs that the former has an identity and is mutable while the latter doesn't have and is immutable.

    1. I knew I should have put in a discussion on Value Objects! I agree that Value Objects are also immutable, but I've never seen anyone suggest that a Value Object has an identity.

      1. Oh, I see the point. Yes, immutable entities are also useful in some cases. For example audit logs need a unique ID to be able to identify them, but it's also essential that an already stored log entry cannot be changed. Modifying them would mean changing the history.

        Unfortunatelly sometimes VOs must also have an identifier because of some technical issues e.g.: when the ORM needs it. I think people regularly use entities just because they are thinking in database level rather than in model/object level. Active Record pattern also enforces this problem.

        1. I agree that you can have immutable Entities, with an identity, as financial transactions work for example. The tricky part is that immutable objects must be composed of other immutable objects, so if you're going to compose a complex report you can't depend on entities such as having a reference to Customer. In that case, a useful pattern is to create Value Objects capturing the data of Customer that you want in the report and refer to that:

          Once you go down this slope, you'll probably find that relational models are in impediment since they drive towards normalization at all costs even if the lifecycle of the Customer and CustomerData is very different.
          The CQRS approach is similar in that the immutable data traveling from your Entities (Command model) to your reports (Query model) are usually immutable Domain Events that the reports subscribed to to compose themselves.

  2. I only have methods which can change the internal state of my entities for fields which can change over time and if the number of fields which can change over time is none then sure the entity could be considered immutable, makes perfect sense to me.

    Another thought on the matter, if your ORM requires getters and setters but you domain logic doesn't change the state the add an "immutable" interface to it and access it in your domain through that.

Comments are closed.