Handling immutable types (part 1)
Immutable types are nice. We like immutable types. They are massively undervalued when building software. Many of us don't take the time to consider the purpose of the class we are creating and how it fits into the structure.
Why immutable types?
It is much easier to reason about a data structure if you know that it will never change. Since they cannot be modified, they are automatically thread safe.
So, some of the benefits include:
- They simplify multithreaded programming
- They can be used to index hash tables
- They simplify state comparison
- For any developer looking to consume, it's much easier to understand how to use them.
On the down side, they do tend to chew up memory, but hey, that’s what garbage collection was invented for, so I’m not too concerned about that.
Immutability in your domain
Immutability is a first class concept in DDD.
Lets say we have the concept of a Person
. That person is unique, just like in the real world. There will only ever be one Person
object to describe an individual. If you are creating multiple objects over time for that same individual; you have application design issues.
I hope you can agree with this sentiment.
Lets look at another example of immutability - that persons Address
:
public struct Address { public string Line1; public string Line2; public string Line3; public string City; public string Postcode; public string Country; }
Now, forgetting for a second that I’ve made this type a struct
. It's common to see something like this yes?
Creation of an Address
would be similar whether it's immutable or mutable. However what happens when a person changes their address?
It's a new address then right? A whole new address. They may have only moved a few doors down, and all that would need to change is the first line of the address - but it's still a completely new house.
The Address
is a good example of an immutable type in DDD. Now taking that an Address is immutable. It simplifies your Person
object.
Lets go ahead and change the person’s address. We might have a method on the Person
similar to this:
public void ChangeAddress(Address address) { Address = address; }
That's about as complicated as that needs to be. Most validations take care of them selves - because Address
is an immutable struct; we can't pass in null or an Address
not fit for use.
Considering what data we then hold about that person - if we wanted, this address can go in as a new record. That way we aren't destroying any data we have on that person.
In the next post (part 2), we will take a look at how we can handle unwieldy immutable types, i.e. types with many constructor parameters.