tags:

views:

245

answers:

8

In class today, my professor was discussing how to structure a class. The course primarily uses Java and I have more Java experience than the teacher (he comes from a C++ background), so I mentioned that in Java one should favor immutability. My professor asked me to justify my answer, and I gave the reasons that I've heard from the Java community:

  1. Safety (especially with threading)
  2. Reduced object count
  3. Allows certain optimizations (especially for garbage collector)

The professor challenged my statement by saying that he'd like to see some statistical measurement of these benefits. I cited a wealth of anecdotal evidence, but even as I did so, I realized he was right: as far as I know, there hasn't been an empirical study of whether immutability actually provides the benefits it promises in real-world code. I know it does from experience, but others' experiences may differ.

So, my question is, have there been any statistical studies done on the effects of immutability in real-world code?

+1  A: 

I think your professor's being overly stubborn (probably deliberately, to push you to a fuller understanding). Really the benefits of immutability are not so much what the complier can do with optimisations, but really that it's much easier for us humans to read and understand. A variable that is guaranteed to be set when the object is created and is guaranteed not to change afterwards, is much easier to grok and reason with than one which is this value now but might be set to some other value later.

This is especially true with threading, in that you don't need to worry about processor caches and monitors and all that boilerplate that comes with avoiding concurrent modifications, when the language guarantees that no such modification can possibly occur.

And once you express the benefits of immutability as "the code is easier to follow", it feels a bit sillier to ask for empirical measurements of productivity increases vis-a-vis "easier-to-followness".

On the other hand, the compiler and Hotspot can probably perform certain optimisations based on knowing that a value can never change - like you I have a feeling that this would take place and is a good things but I'm not sure of the details. It's a lot more likely that there will be empirical data for the types of optimisation that can occur, and how much faster the resulting code is.

Andrzej Doyle
+1  A: 
  • Don't argue with the prof. You have nothing to gain.
  • These are open questions, like dynamic vs static typing. We sometimes think functional techniques involving immutable data are better for various reasons, but it's mostly a matter of style so far.
DigitalRoss
Surely there's a line between arguing and engaging your professor in an open and earnest discussion in the spirit of debate.
Drew Noakes
I agree completely. I was guessing based on the tone of the question...
DigitalRoss
The professor in question does a lot to encourage this kind of discussion.
Imagist
+2  A: 

The biggest advantage of immutability in Java, in my opinion, is simplicity. It becomes much simpler to reason about the state of an object, if that state cannot change. This is of course even more important in a multi-threaded environment, but even in simple, linear single-threaded programs it can make things far easier to understand.

See this page for more examples.

Avi
+1  A: 

What would you objectively measure? GC and object count could be measured with mutable/immutable versions of the same program (although how typical that would be would be subjective, so this is a pretty weak argument). I can't imagine how you could measure the removal of threading bugs, except maybe anecdotally by comparison with a real world example of a production application plagued by intermittent issues fixed by adding immutability.

Steve B.
A: 

Immutability is a good thing for value objects. But how about other things? Imagine an object that creates a statistic:

Stats s = new Stats ();

... some loop ...
     s.count ();

s.end ();
s.print ();

which should print "Processed 536.21 rows/s". How do you plan to implement count() with an immutable? Even if you use an immutable value object for the counter itself, s can't be immutable since it would have to replace the counter object inside of itself. The only way out would be:

     s = s.count ();

which means to copy the state of s for every round in the loop. While this can be done, it surely isn't as efficient as incrementing the internal counter.

Moreover, most people would fail to use this API right because they would expect count() to modify the state of the object instead of returning a new one. So in this case, it would create more bugs.

Aaron Digulla
Most of the points you raised could be solved by proper documentation of the Stats class.
Kevlar
I certainly wouldn't expect a method called "count" to modify the state of the object it was invoked on. I'd expect it to count something and return the result. If you're going to have side-effects, use a name that makes it obvious. eg: "increment" would probably be a better choice in this case.
Laurence Gonsalves
@Aaron: To back up Kevlar's point, your example doesn't seem anymore confusing than the way string.Replace(...) returns a new object, rather than mutating a string in place. Moreover, functional programming style discourages the use of variables, so you probably wouldn't see "s = s.count()" too often. Its much more idiomatic to use fold_left: let res = List.fold_left (fun s x -> s.process(x) ) processor items; res.count()
Juliet
I needed a simple example. As for functional programming: Most people can't reprogram their brain to get used to it. So the question remains how useful immutables can/should be in an imperative language. My opinion: Immutables are nice to solve a couple of cases but for others, they are more problem than solution.
Aaron Digulla
+5  A: 

I would point to Item 15 in Effective Java. The value of immutability is in the design (and it isn't always appropriate - it is just a good first approximation) and design preferences are rarely argued from a statistical point of view, but we have seen mutable objects (Calendar, Date) that have gone really bad, and serious replacements (JodaTime, JSR-310) have opted for immutability.

Yishai
+1: awesome link :) And I completely agree: I've never seen anyone say "statistics prove this design is superior to this other design", but I have seen a lot of "such and such is a time-tested best practice in most applications".
Juliet
A: 

As other comments have claimed, it would be very, very hard to collect statistics on the merits of immutable objects, because it would be virtually impossible to find control cases - pairs of software applications which are alike in every way, except that one uses immutable objects and the other does not. (In nearly every case, I would claim that one version of that software was written some time after the other, and learned numerous lessons from the first, and so improvements in performance will have many causes.) Any experienced programmer who thinks about this for a moment ought to realize this. I think your professor is trying to deflect your suggestion.

Meanwhile, it is very easy to make cogent arguments in favor of immutability, at least in Java, and probably in C# and other OO languages. As Yishai states, Effective Java makes this argument well. So does the copy of Java Concurrency in Practice sitting on my bookshelf.

Paul Brinkley
+2  A: 

So, my question is, have there been any statistical studies done on the effects of immutability in real-world code?

I'd argue that your professor is just being obtuse -- not necessarily intentionally or even a bad thing. Its just that the question is too vague. Two real problems with the question:

  • "Statistical studies on the effect of [x]" doesn't really mean anything if you don't specify what kind of measurements you're looking for.
  • "Real-world code" doesn't really mean anything unless you state a specific domain. Real world code includes scientific computing, game development, blog engines, automated proof generators, stored procedures, operating system kernals, etc

For what its worth, the ability for the compiler to optimize immutable objects is well-documented. Off the top of my head:

  • The Haskell compiler performs deforestation (also called short-cut fusion), where Haskell will transform the expression map f . map g to map f . g. Since Haskell functions are immutable, these expressions are guaranteed to produce equivalent output, but the second function runs twice as fast since we don't need to create an intermediate list.
  • Common subexpression elimination where we could convert x = foo(12); y = foo(12) to temp = foo(12); x = temp; y = temp; is only possible if the compiler can guarantee foo is a pure function. To my knowledge, the D compiler can perform substitutions like this using the pure and immutable keywords. If I remember correctly, some C and C++ compilers will aggressively optimize calls to these functions marked "pure" (or whatever the equivalent keyword is).
  • So long as we don't have mutable state, a sufficiently smart compiler can execute linear blocks of code multiple threads with a guarantee that we won't corrupt the state of variables in another thread.

Regarding concurrency, the pitfalls of concurrency using mutable state are well-documented and don't need to be restated.


Sure, this is all anecdotal evidence, but that's pretty much the best you'll get. The immutable vs mutable debate is largely a pissing match, and you are not going to find a paper making a sweeping generalization like "functional programming is superior to imperative programming".

At most, you'll probably find that you can summarize the benefits of immutable vs mutable in a set of best practices rather than as codified studies and statistics. For example, mutable state is the enemy of multithreaded programming; on the other hand, mutable queues and arrays are often easier to write and more efficient in practice than their immutable variants.

It takes practice, but eventually you learn to use the right tool for the job, rather than shoehorning your favorite pet paradigm into project.

Juliet