When first learning object oriented programming (OOP), you typically create a very basic object and implement getters and setters. From that point forward, objects are this magical world of malleable data. However, you’d be surprised to find that sometimes removing the ability to alter the data in an object can lead to more straightforward and easier to understand code. This is the case with immutable objects.
In programming, an immutable object is an object whose state cannot be modified after it is created. While at first this may not seem very useful as often times the getters and setters are the first functions created for an object, there are many clear benefits to immutable objects.
Given that by definition an immutable object cannot be changed, you will not have any synchronization issues when using them. No matter which thread is accessing the version of an object, it is guaranteed to have the same state it originally had. If one thread needs a new version or altered version of that object, it must create a new one therefore any other threads will still have the original object. This leads to simpler, more thread safe code.
PHP specifically does not support threads out of the box, so this benefit isn’t as immediately obvious when using that language.
Once you are given an immutable object and verify its state, you know it will always remain safe. No other thread or background process in your program will be able to change that object without your direct knowledge. Furthermore, all of the data needed to have a complete object should be provided. One situation in which this may be extremely useful it programs that need to have high security. For instance, if given an object with a filename to write to you know nothing can change that location on you.
For example, the code below outlines how constructing an immutable object may look. Since the
SimplePerson class requires all of it’s data in the constructor, we can be sure all the necessary data to have a valid object will always be present. If instead we had used setters for this data, there is no guarantee that a function like
setAge($age) would have been called by the time we received the object.
create(new SimplePerson(â€˜Joe’, 42));
When passing immutable objects around your code base, you can better encapsulate your methods. Since you know the object won’t change, anytime you pass this object to another method you can be positive that doing so will not alter the original state of that object in the calling code.
This also means these objects can always be passed by reference, and there is no need to have to worry about solutions like defensive copying.
Furthermore, debugging will be easier when any issues arise. You can be certain that the state the object is given to you in doesn’t change and therefore more easily track down where bugs started from.
The code below helps outline this benefit. In this code, both auto body shops we have created will have a Mercedes car associated with it since our object was not immutable. This was not the intended result, it was simple a bad side effect of using mutable objects.
setMake(â€˜BMW’); $autoShopOne = new AutoBodyShop($car); $car->setMake(â€˜Mercedes’); $autoShopTwo = new AutoBodyShop($car);
Going hand in hand with better encapsulation is code that is simpler to test. The benefits of testable code are obvious and lead to a more robust and error free code base. When your code is designed in a way that lead to less side effects, there are less confusing code paths to track down.
Any piece of code working against an immutable object does not need to be concerned with affecting other areas of your code using that object. This means there are less intermingled and moving parts in your code. Therefore, your code will be cleaner and easier to understand.
In conclusion, making use of immutability has clear benefits. If done correctly it can lead to more understandable and testable code which are large wins in any codebase. Depending on the language you are using these benefits may be larger than others. In multi-threaded programs for instance immutability will leave much less room for confusion and side effects in your code. However, regardless of the language you’re sure to get some advantages from this functionality.
This was originally posted here.