Immutability is one of the most important design concepts for building stable applications. The basic principle states that once a state is written, it can only be read later without the possibility of modifying it. If we need to change the state, we have to create a new instance and replace the whole object with another one.
Data types can therefore be very roughly divided into two broad categories:
Mutable objects can be changed internally. That is, they provide operations that, when called in different combinations, cause us to get different results. Immutability tries to prevent this behavior.
A class is immutable precisely if the instance data cannot be changed in any way after the instance is created.
So all data is fixed in the constructor. All scalar data types are also automatically immutable.
Designing applications with immutable states provides a fundamental advantage in the safety of executing operations. If we know that once written, the data cannot be changed (mutated) later, we can, for example, debug very reliably, or split the application into sub-functions without the risk of forgetting any of the intermediate states.
From a performance perspective, we can automatically say of immutable objects that they can be cached indefinitely, because they will never be out of date.
By far the most common use of immutable objects in PHP is the
DateTimeImmutable object, which once created can only be called by formatting methods. If we modify the internal settings, the method will return a new instance. This feature is crucial when using an ORM that uses the so-called identity pattern - it allows us, for example, to guarantee that when we read the creation date of an order, it will be the same everywhere in the application and the referential integrity will not be corrupted.
A concrete example of a mutable object:
$date = new DateTime('2021-05-14');$tomorrow = $date->modify('+1 day');echo $date->format('Y-m-d'); // 2021-05-15echo $tomorrow->format('Y-m-d'); // 2021-05-15
The same date was printed because the
modify() method only changed the internal state of the
DateTime object and returned the same instance. Thus, there was no so-called mutation of internal state, which is a basic behavior of object-oriented programming. Updating the variable also changed the original one.
And now an example of an immutable object:
$date = new DateTimeImmutable('2021-05-14');$tomorrow = $date->modify('+1 day');echo $date->format('Y-m-d'); // 2021-05-14echo $tomorrow->format('Y-m-d'); // 2021-05-15
DateTimeImmutable object is immutable, which means that its internal state never changes. A new modified instance (also immutable) is stored in the variable after the
modify() method is called. If we did not store the new value in the variable, it would not be usable later.
The original value is never touched and remains safely stored.
Unless you have a very good reason to make it mutable, always write a class or function as immutable. This will simplify your design in the future.
Mutable classes should change as little as possible. I always recommend documenting the behavior of immutability.
Perhaps the only drawback with immutability is that a new instance must be created with each attribute change, which has a minor performance impact. If your application (like most applications) tends to display data and change it less frequently, this disadvantage is rather insignificant with the performance of today's computers.
What should not be immutable:
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu: