What is immutability and why should I worry about it?

OopImmutability

Oop Problem Overview


I've read a couple of articles on immutability but still don't follow the concept very well.

I made a thread on here recently which mentioned immutability, but as this is a topic in itself, I am making a dedicated thread now.

I mentioned in the past thread that I thought immutability is the process of making an object read only and giving it low visibility. Another member said it didn't really have anything to do with that. This page (part of a series) uses an example of an immutable class/struct and it uses readonly and other concepts to lock it down.

What exactly is the definition of state in the case of this example? State is a concept which I haven't really grasped.

From a design guideline perspective, an immutable class must be one which does not accept user input and really would just return values?

My understanding is that any object which just returns information should be immutable and "locked down", right? So if I want to return the current time in a dedicated class with that one method, I should use a reference type as that will work a reference of the type and thus I benefit from immutability.

Oop Solutions


Solution 1 - Oop

What is Immutability?

  • Immutability is applied primarily to objects (strings, arrays, a custom Animal class)
  • Typically, if there is an immutable version of a class, a mutable version is also available. For instance, Objective-C and Cocoa define both an NSString class (immutable) and an NSMutableString class.
  • If an object is immutable, it can't be changed after it is created (basically read-only). You could think of it as "only the constructor can change the object".

This doesn't directly have anything to do with user input; not even your code can change the value of an immutable object. However, you can always create a new immutable object to replace it. Here's a pseudocode example; note that in many languages you can simply do myString = "hello"; instead of using a constructor as I did below, but I included it for clarity:

String myString = new ImmutableString("hello");
myString.appendString(" world"); // Can't do this
myString.setValue("hello world"); // Can't do this
myString = new ImmutableString("hello world"); // OK

You mention "an object that just returns information"; this doesn't automatically make it a good candidate for immutability. Immutable objects tend to always return the same value that they were constructed with, so I'm inclined to say the current time wouldn't be ideal since that changes often. However, you could have a MomentOfTime class that is created with a specific timestamp and always returns that one timestamp in the future.

Benefits of Immutabilty

  • If you pass an object to another function/method, you shouldn't have to worry about whether that object will have the same value after the function returns. For instance:

      String myString = "HeLLo WoRLd";
      String lowercasedString = lowercase(myString);
      print myString + " was converted to " + lowercasedString;
    

    What if the implementation of lowercase() changed myString as it was creating a lowercase version? The third line wouldn't give you the result you wanted. Of course, a good lowercase() function wouldn't do this, but you're guaranteed this fact if myString is immutable. As such, immutable objects can help enforce good object-oriented programming practices.

  • It's easier to make an immutable object thread-safe

  • It potentially simplifies the implementation of the class (nice if you're the one writing the class)

State

If you were to take all of an object's instance variables and write down their values on paper, that would be the state of that object at that given moment. The state of the program is the state of all its objects at a given moment. State changes rapidly over time; a program needs to change state in order to continue running.

Immutable objects, however, have fixed state over time. Once created, the state of an immutable object doesn't change although the state of the program as a whole might. This makes it easier to keep track of what is happening (and see other benefits above).

Solution 2 - Oop

Immutability

Simply put, memory is immutable when it is not modified after being initialised.

Programs written in imperative languages such as C, Java and C# may manipulate in-memory data at will. An area of physical memory, once set aside, may be modified in whole or part by a thread of execution at any time during the program's execution. In fact, imperative languages encourage this way of programming.

Writing programs in this way has been incredibly successful for single-threaded applications. However as modern application development moves towards multiple concurrent threads of operation within a single process, a world of potential problems and complexity is introduced.

When there is only one thread of execution, you can imagine that this single thread 'owns' all of the data in memory, and so therefore can manipulate it at will. However, there is no implicit concept of ownership when multiple executing threads are involved.

Instead, this burden falls upon the programmer who must go to great pains to ensure that in-memory structures are in a consistent state for all readers. Locking constructs must be used in careful measure to prohibit one thread from seeing data while it is being updated by another thread. Without this coordination, a thread would inevitably consume data that was only halfway through being updated. The outcome from such a situation is unpredictable and often catastrophic. Furthermore, making locking work correctly in code is notoriously difficult and when done badly can cripple performance or, in the worst case, case deadlocks that halt execution irrecoverably.

Using immutable data structures alleviates the need to introduce complex locking into code. When a section of memory is guaranteed not to change during the lifetime of a program then multiple readers may access the memory simultaneously. It is not possible for them to observe that particular data in an inconsistent state.

Many functional programming languages, such as Lisp, Haskell, Erlang, F# and Clojure, encourage immutable data structures by their very nature. It is for this reason that they are enjoying a resurgence of interest as we move towards increasingly complex multi-threaded application development and many-computer computer architectures.

State

The state of an application can simply be thought of as the contents of all the memory and CPU registers at a given point in time.

Logically, a program's state can be divided into two:

  1. The state of the heap
  2. The state of the stack of each executing thread

In managed environments such as C# and Java, one thread cannot access the memory of another. Therefore, each thread 'owns' the state of its stack. The stack can be thought of as holding local variables and parameters of value type (struct), and the references to objects. These values are isolated from outside threads.

However, data on the heap is shareable amongst all threads, hence care must be taken to control concurrent access. All reference-type (class) object instances are stored on the heap.

In OOP, the state of an instance of a class is determined by its fields. These fields are stored on the heap and so are accessible from all threads. If a class defines methods that allow fields to be modified after the constructor completes, then the class is mutable (not immutable). If the fields cannot be changed in any way, then the type is immutable. It is important to note that a class with all C# readonly/Java final fields is not necessarily immutable. These constructs ensure the reference cannot change, but not the referenced object. For example, a field may have an unchangeable reference to a list of objects, but the actual content of the list may be modified at any time.

By defining a type as being truly immutable, its state can be considered frozen and therefore the type is safe for access by multiple threads.

In practice, it can be inconvenient to define all of your types as immutable. To modify the a value on an immutable type can involve a fair bit of memory copying. Some languages make this process easier than others, but either way the CPU will end up doing some extra work. Many factors contribute to determine whether the time spent copying memory outweighs the impact of locking contentions.

A lot of research has gone into the development of immutable data structures such as lists and trees. When using such structures, say a list, the 'add' operation will return a reference to a new list with the new item added. References to the previous list do not see any change and still have a consistent view of the data.

Solution 3 - Oop

To put it simple: Once you create an immutable object, there's no way to change the contents of that object. Examples of .Net immutable objects are String and Uri.

When you modify a string, you simply get a new string. The original string will not change. An Uri has only readonly properties and no methods available to change the content of the Uri.

Cases that immutable objects are important are various and in most of the cases have to do with security. The Uri is a good example here. (e.g. You don't want a Uri to be changed by some untrusted code.) This means you can pass a reference to a immutable object around without having to worry the contents will ever change.

Hope this helps.

Solution 4 - Oop

Things that are immutable never change. Mutable things can change. Mutable things mutate. Immutable things appear to change but actually create a new mutable thing.

For example here is a map in Clojure

(def imap {1 "1" 2 "2"})
(conj imap [3 "3"])
(println imap)

The first line creates a new immutable Clojure map. The second line conjoins 3 and "3" to the map. This may appear as if it is modifying the old map but in reality it is returning a new map with 3 "3" added. This is a prime example of immutability. If this had been a mutable map it would have simply added 3 "3" directly to the same old map. The third line prints the map

{3 "3", 1 "1", 2 "2"}

Immutability helps keep code clean and safe. This and other reasons is why functional programming languages tend to lean towards immutability and less statefulness.

Solution 5 - Oop

Good question.

Multi-threading. If all types are immutable then race conditions don't exist and you're safe to throw as many threads at the code as you wish.

Obviously you can't accomplish that much without mutability save complex calculations so you usually need some mutability to create functional business software. However it is worth recognising where immutability should lie such as anything transactional.

Look up functional programming and the concept of purity for more information on the philosophy. The more you store on the call stack (the params you're passing to methods) as opposed to making them available via references such as collections or statically available objects the more pure your program is and the less prone to race conditions you will be. With more multi-cores these days this topic is more important.

Also immutability reduces the amount of possibilities in the program which reduces potential complexity and potential for bugs.

Solution 6 - Oop

An immutable object is something which you can safely assume isn't going to change; it has the important property that everyone using it can assume they're seeing the same value.

Immutability usually also means you can think of the object as being a "value", and that there's no effective difference between identical copies of the object and the object itself.

Solution 7 - Oop

Let me add one more thing. Besides all that was mentioned above you also want immutability for:

Solution 8 - Oop

Making things immutable prevents a large number of common mistakes.

For example, a Student should never have their student # change on them. If you don't provide a way to set the variable (and make it const, or final, or whatever your language supports) then you can enforce that at compile time.

If things are mutable and you don't want them to change when you pass them around you need to make a defencive copy that you pass. Then if the method/function you call changes the copy of the item the original is untouched.

Making things immutable means you do not have to remember (or take the time/memory) to make defencive copies.

If you really work at it, and think about each variable you make, you will find that the vast majority (I typically have 90-95%) of your variables never change once they are given a value. Doing this makes programs easier to follow and reduces the number of bugs.

To answer your question on state, state is the values that variables of an "object" (be that a class or a struct) have. If you took a person "object" state would be things like eye colour, hair colour, hair length, etc... some of those (say eye colour) do not change while others, such as hair length do change.

Solution 9 - Oop

"... why should I worry about it?"

A practical example is repetitive concatenation of strings. In .NET for example:

string SlowStringAppend(string [] files)
{
    // Declare an string
    string result="";
    
    for (int i=0;i<files.length;i++)
    {
        // result is a completely new string equal to itself plus the content of the new
        // file
        result = result + File.ReadAllText(files[i]);
    }
    
    return result;
}    
    
string EfficientStringAppend(string [] files)
{
    // Stringbuilder manages a internal data buffer that will only be expanded when absolutely necessary
    StringBuilder result=new SringBuilder();
    
    for (int i=0;i<files.length;i++)
    {
        // The pre-allocated buffer (result) is appended to with the new string 
        // and only expands when necessary.  It doubles in size each expansion
        // so need for allocations become less common as it grows in size. 
        result.Append(File.ReadAllText(files[i]));
    }
    
    return result.ToString();
}

Unfortunately using the first (slow) function approach is still commonly used. An understanding of immutability makes it very clear why using StringBuilder is so important.

Solution 10 - Oop

You cannot change an immutable object, therefore you must replace it.... "to change it". i.e. replace then discard. "Replacing" in this sense means changing the pointer from one memory location (of the old value) to another (for the new value).

Note that in doing so we now using additional memory. Some for the old value, some for the new value. Also note, some people get confused because they look at code, such as:

string mystring = "inital value";
mystring = "new value";
System.Console.WriteLine(mystring); // Outputs "new value";

and think to themselves, "but I am changing it, look right there, in black and white! mystring outputs 'new value'...... I thought you said i couldn't change it?!!"

But actually under the hood, whats happening is this allocation of new memory i.e. mystring is now pointing at a different memory address and space. "Immutable" in this sense, is not referring to the value of mystring but rather the memory used by the variable mystring to store its value.

In certain languages the memory storing the old value must be manually cleaned up i.e. the programmer must explicitly release it..... and remember to do so. In other languages this is an automatic feature of the language i.e. garbage collection in .Net.

One of the places this really blows out re:memory usage is in highly iterative loops, specially with strings as in Ashs' post. Say you were building an HTML page in an iterative loop, where you constantly appended the next HTML block to the last and, just for kicks, you were doing this on a high volume server. This constant allocation of "new value memory" can quickly get expensive, and ultimately fatal, if the "old value memory", is not properly cleaned up.

Another problem is that some people assume things like garbage collection (GC) happens immediately. But it doesn't. There are various optimizations that occur such that garbage collection is set to occur during the more idle periods. So there can be a significant delay between when the memory is marked as discarded and when it is actually freed by the garbage collector.... so you can suffer large memory usage spikes if you simply defer the problem to the GC.

If the GC doesn't get a chance to operate before you run out of memory, then things wont necessarily fall over like in other languages that don't have automatic garbage collection. Instead the GC will kick in as the highest priority process to free up the discarded memory, no matter how bad the timing, and become a blocking process while it cleans things up. Obviously, this isn't cool.

So basically, you need to code with these things in mind and look into the documentation for the languages you are using for the best practices/patterns that allow you to avoid/mitigate this risk.

As in Ashs' post, in .Net and with strings, the recommended practice is to use the mutable StringBuilder class, rather than the immutable string classes when it comes to the need to constantly change a strings value.

Other languages/types will similarly have their own workarounds.

Solution 11 - Oop

Why Immutability?

  1. They are less prone to error and are more secure.

  2. Immutable classes are easier to design, implement, and use than mutable classes.

  3. Immutable objects are thread-safe so there is no synchronization issues.

  4. Immutable objects are good Map keys and Set elements, since these typically do not change once created.

  5. Immutability makes it easier to write, use and reason about the code (class invariant is established once and then unchanged).

  6. Immutability makes it easier to parallelize program as there are no conflicts among objects.

  7. The internal state of program will be consistent even if you have exceptions.

  8. References to immutable objects can be cached as they are not going to change.(i.e in Hashing it provide fast operations).

See my blog for a more detailed answer:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html

Solution 12 - Oop

Look, I haven't read the links that you have posted.

However, here is my understanding.
Every program holds some knowledge of it's data (State), which can change either by user-input/external changes etc.

Variables (values which change) are kept to maintain state. Immutable means some data which doesn't change. You can say, it is same as readonly or constant in some way (it can be seen it that way).

AFAIK, functional programming has things immutable (i.e. you cannot use assignment to a variable holding the value. What you can do is create another variable which can hold the original value + changes).

.net has string class which is an example.
i.e. You can't modify string in its place

string s = "hello"; I can write s.Replace("el", "a"); But this won't modify the contents of variable s.

What I can do is s = s.Replace("el","a");
This will create a new variable & assign its value to s (overwriting content of s).

Experts can correct mistakes if I have, in my understanding.

EDIT: Immutable = Unassignable once it is holding some value & can't be replaced in place (maybe?)

Solution 13 - Oop

An example of the potential performance benefits offered by immutable objects is available in the WPF API. A common base class of many WPF types is Freezable.

Several WPF examples suggest that freezing objects (making them immutable at runtime) can improve application performance significantly as locking and copying is not required.

Personally I wish the concept of immutability was easier to express in the language I use most often, C#. There is a readonly modifier available for fields. I would like to see a readonly modifier on types as well that would only be allowed for types that only have readonly fields that are of readonly types. Essentially this means that all state would need to be injected at construction time, and that and entire object graph would be frozen. I imagine that were this metadata intrinsic to the CLR then it could be easily used to optimise garbage analysis for GC.

Solution 14 - Oop

Sorry, why does immutability prevent race conditions (in this example, write after read hazards)?

shared v = Integer(3)
v = Integer(v.value() + 1) # in parallel

Solution 15 - Oop

Immutability is about values, and values are about facts. Something has value if is unchangeable, because if something can be changed, then it means that no specific value can be connected to it. Object was initialized with state A and during program execution was mutated to state B and state C. It means that object doesn't represent single specific value but is only a container, abstraction on a place in the memory, nothing more. You can't have trust to such container, you can not believe that this container has the value you suppose should have.

Let's go to example - lets imagine that in code is created instance of Book class.

Book bookPotter =  new Book();
bookPotter.setAuthor('J.K Rowling');
bookPotter.setTitle('Harry Potter');

This instance has some fields set like author and title. Everything is ok, but in some part of the code again setters are used.

Book bookLor =  bookPotter; // only reference pass
bookLor.setAuthor('J.R.R Tolkien');
bookLor.setTitle('Lords of The Rings');

Don't be cheated by different variable name, really it is the same instance. The code is using setters on the same instance again. It means that bookPotter was never really the Harry Potter book, bookPotter is only pointer to the place where unknown book is located. That said, it looks like it is more a shelf then the book. What trust you can have to such object? It is Harry Potter book or LoR book or neither?

Mutable instance of a class is only a pointer to an unknown state with the class characteristics.

How then avoid mutation? It is quite easy in rules:

  • construct object with wanted state via constructor or builder
  • don't create setters for encapsulated state of the object
  • don't change any encapsulated state of the object in any of its methods

These few rules will allow to have more predictable and more reliable objects. Back to our example and book following above rules:

Book bookPotter =  new Book('J.K Rowling', 'Harry Potter');
Book bookLor = new Book('J.R.R Tolkien', 'Lord of The Rings');

Everything is set during constructing phase, in this case constructor, but for bigger structures it can be a builder. No setters exist in objects, book can not mutate to different one. In such case bookPotter represents value of Harry Potter book and you can be sure that this is unchangeable fact.

If you are interested in wider scope of immutability, in this medium article is more about the subject in relation to JavaScript - https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGurdeepSView Question on Stackoverflow
Solution 1 - OopPCheeseView Answer on Stackoverflow
Solution 2 - OopDrew NoakesView Answer on Stackoverflow
Solution 3 - OopJeroen LandheerView Answer on Stackoverflow
Solution 4 - OopRayneView Answer on Stackoverflow
Solution 5 - OopQuibblesomeView Answer on Stackoverflow
Solution 6 - OopMandyKView Answer on Stackoverflow
Solution 7 - OopDavid PokludaView Answer on Stackoverflow
Solution 8 - OopTofuBeerView Answer on Stackoverflow
Solution 9 - OopAshView Answer on Stackoverflow
Solution 10 - OoprismView Answer on Stackoverflow
Solution 11 - OopRajesh DixitView Answer on Stackoverflow
Solution 12 - OopshahkalpeshView Answer on Stackoverflow
Solution 13 - OopDrew NoakesView Answer on Stackoverflow
Solution 14 - OopgatoatigradoView Answer on Stackoverflow
Solution 15 - OopMaciej SikoraView Answer on Stackoverflow