tags:

views:

1322

answers:

14

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.

+5  A: 

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.

Jeroen Landheer
+2  A: 

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.

MandyK
A: 

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?)

shahkalpesh
+3  A: 

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.

Rayne
If conj is creating a new map, why doesn't this map has a new name? Put another way: how do I access imap's old value? If I can't, then clearnly conj _is_ modifying the map
If you don't use imaps old value Clojure would garbage collect it of course... You can keep imaps old value by simply using it again, for example assigning it to a var.
Rayne
I don't really get that but then, I don't know Clojure so.. :)
@iraimbilanja, The way I explained immutability with Clojure is the same concept as with OOP but is explained in a way that seems bizarre. Immutability in functional programming language really shines.
Rayne
Wait... got it... so the value of imap is immutable but imap itself is mutable, i.e. it can be made to refer to a different object. so it's not a purely functional thing, I see.
def creates a new Clojure var. That var can be changed to refer to a different value. Clojure isn't purely functional, but it favors an immutable approach. There are refs and atoms to have actual mutable state.
Rayne
+1  A: 

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.

TofuBeer
+2  A: 

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.

Quibblesome
+2  A: 

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

David Pokluda
+1 for value objects. Immutability may or may not make sense in a lot of other cases depending on how you're using your objects, but I think it almost always makes sense to make value objects immutable.
John Price
How does this answer the question?
Rayne
+31  A: 

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).

PCheese
I would vote this up if you didn't act as if it only applied to OOP.
Rayne
@Rayne - Could you give an example of immutability in something other than OOP? The const keyword can work in a similar fashion; however I think of const as compiler-enforced and immutability as contract-enforced (that is, it's up to developer to make sure it's implemented correctly).
PCheese
@PCheese View my post below, I made an example in a functional programming language called Clojure.
Rayne
Nice work!!!!! Clears out some cobwebs for me.
Jason Watts
+5  A: 

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 a mutable field is not necessarily immutable. For example, in C#, just because a field of type List<object> is defined as being readonly, 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.

Drew Noakes
A: 

I asked a similar question that you may find helpful: Sell me on using const correctness. It's more focused on C++, but some of the answers are generically useful.

Jason Baker
+1  A: 

"... 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.

Ash
+1  A: 

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.

rism
A: 

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.

Drew Noakes
A: 

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
gatoatigrado