On a recent project all our domain objects are all Immutable. The reason for that is that it makes multithreading easier. Immutable means that an object properties cannot be changed once it is constructed.
The problem
Suppose we have the following object:
Public class User { public int Id {get;} public string Username {get;} public string PhoneNumber {get;} public string FirstName {get;} public string LastName {get;} }
This looks fine, however what would we do if have an existing object and we want to change the name?
That would not be possible so let’s say we add a constructor like this:
public class User { public int Id {get;} public string Username {get;} public string PhoneNumber {get;} public string FirstName {get;} public string LastName {get;} public User(User user, string username) : this(user) { Username = username; } public User(User user) { Id = user.Id; Username = user.Username; PhoneNumber = user.PhoneNumber; FirstName = user.FirstName; LastName = user.LastName; } }
Problem solved right? Lets add one for firstname and lastname
public User(User user, string firstName, string lastName) : this(user) { FirstName = firstName; LastName = lastName; }
OK, fixed that.. let’s add one for phonenumer.. Oh wait… we can’t. Because we already declared one with a string argument. The other problem with this is that we get a load of constructors and that creates a lot of maintenance and a lot of clutter.
Builders
A builder is a class that generates another class for us. So lets create a builder for our user class:
public class UserBuilder { private int Id { get; set; } private string Username { get; set; } private string PhoneNumber { get; set; } private string FirstName { get; set; } private string LastName { get; set; } public static UserBuilder New() { return new UserBuilder(); } public UserBuilder WithId(int id) { Id = id; return this; } public UserBuilder WithUsername(string username) { Username = username; return this; } public UserBuilder WithFirstName(string firstName) { FirstName = firstName; return this; } public UserBuilder WithLastName(string lastName) { LastName = lastName; return this; } public User Build() { return new User(Id,Username, PhoneNumber,FirstName,LastName); } }
This codes allows us the following to construct a user:
var user = UserBuilder.New() .WithUsername("Username") .WithFirstName("Marco") .WithLastName("Sikkens") .Build();
This is a nice and clean LINQ like syntax to construct objects. But be aware this code is NOT immutable. So only after the Build() method is called an immutable is returned.