Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I love the immutable "pattern" because of its strengths, and in the past I have found it beneficial to design systems with immutable data types (some, most or even all). Often when I do so, I find myself writing fewer bugs and debugging is much easier.

However, my peers in general shy away from immutable. They are not inexperienced at all (far from it), yet they write data objects the classic way - private members with a getter and a setter for every member. Then usually their constructors take no arguments, or maybe just take some arguments for convenience. So often, creating an object looks like this:

Foo a = new Foo();
a.setProperty1("asdf");
a.setProperty2("bcde");

Maybe they do that everywhere. Maybe they don't even define a constructor that takes those two strings, no matter how important they are. And maybe they don't change the value of those strings later and never need to. Clearly if those things are true, the object would be better designed as immutable, right? (constructor takes the two properties, no setters at all).

How do you decide if an object type should be designed as immutable? Is there a good set of criteria to judge it by?

I currently am debating whether to switch a few data types in my own project to immutable, but I would have to justify it to my peers, and the data in the types might (VERY rarely) change - at which time you can of course change it the immutable way (create a new one, copying the properties from the old object except for the ones that you want to change). But I'm not sure if this is just my love for immutables showing through, or if there is an actual need for/benefit from them.

share|improve this question
1  
Program in Erlang and the whole problem is solved, everything is immutable –  Zachary K Feb 28 '12 at 18:16
    
@ZacharyK I was actually thinking of mentioning something about functional programming, but refrained due to my limited experience with functional programming languages. –  Ricket Feb 28 '12 at 20:43

7 Answers 7

And maybe they don't change the value of those strings later and never need to. Clearly if those things are true, the object would be better designed as immutable, right?

Somewhat counter-intuitively, never needing to change the strings later on is a pretty good argument that it doesn't matter if the objects are immutable or not. The programmer is already treating them as effectively immutable whether the compiler enforces it or not.

Immutability doesn't usually hurt, but it doesn't always help either. The easy way to tell if your object might benefit from immutability is if you ever need to make a copy of the object or acquire a mutex before changing it. If it never changes, then immutability doesn't really buy you anything, and sometimes makes things more complicated.

You do have a good point about the risk of constructing an object in an invalid state, but that's really a separate issue from immutability. An object can be both mutable and always in a valid state after construction.

The exception to that rule is that since Java supports neither named parameters nor default parameters, it can sometimes get unwieldy to design a class that guarantees a valid object just using overloaded constructors. Not so much with the two-property case, but then there's something to be said for consistency as well, if that pattern is frequent with similar but larger classes in other parts of your code.

share|improve this answer
    
I find it curious that discussions of mutability fail to recognize the relationship between immutability and the ways in which an object can be safely exposed or shared. A reference to a deeply-immutable class object can safely be shared with untrusted code. A reference to an instance of a mutable class may be shared if everyone who holds a reference can be trusted never to modify the object or expose it to code that might do so. A reference to a class instance that may be mutated should generally not be shared at all. If only one reference to an object exists anywhere in the universe... –  supercat Nov 22 at 23:38
    
...and nothing has queried its "identity hashcode", used it for locking, or otherwise accessed its "hidden Object features", then changing an object directly would be semantically no different from overwriting the reference with a reference to a new object which was identical but for the indicated change. One of the biggest semantic weaknesses in Java, IMHO, is that it has no means by which code can indicate that a variable should only the only non-ephemeral reference to something; references should only be passable to methods that can't possibly keep a copy after they return. –  supercat Nov 22 at 23:43

The answer is somewhat language-dependent. Your code looks like Java, where this problem is about as difficult as possible. In Java, objects can only be passed by reference, and clone is completely broken.

There is no simple answer, but for certain you want to make small-ish value objects immutable. Java correctly made Strings immutable, but incorrectly made Date and Calendar mutable.

So definitely make small value objects immutable, and implement a copy constructor. Forget all about Cloneable, it's so badly designed that it's useless.

For larger value objects, if it is inconvenient to make them immutable, then make them easy to copy.

share|improve this answer
    
Sounds a lot like how to choose between stack and heap when writing C or C++ :) –  Ricket Feb 29 '12 at 2:26
    
@Ricket: not so much IMO. Stack/heap depends on the object lifetime. It is very common in C++ to have mutable objects on the stack. –  kevin cline Mar 14 at 18:45

There are two major ways to decide if an object is immutable.

a) Based on the nature of the Object

It is easy to catch these situations because we know that these objects will not change after it is constructed. For example if you are have a RequestHistory entity and by nature history entities do not change once it is constructed. These objects can be straight forward designed as immutable classes. Keep in mind that Request Object is mutuable as it can change its state and whom it is assigned to etc over the time but request history do not change. For example, there was a history element created last week when it moved from submitted to assigned state AND this history entitiy can never change. So this is a classic immutable case.

b) Based on the design choice, external factors

This is similar to java.lang.String example. Strings can actually change over the time but by design, they have made it as immutable due to caching/string pool/concurrency factors. Similary the caching/concurrency etc can play a good role in making an object immuatble if caching/concurrency and related performance is vital in the application. But this decision should be taken very carefully after anlyzing all the impacts.

The main advantage of immutable objects is they are not subjected to tumble-weed pattern.i.e the object will not pick up any change over the life time and it makes the coding and maintenance very very easier.

share|improve this answer

I currently am debating whether to switch a few data types in my own project to immutable, but I would have to justify it to my peers, and the data in the types might (VERY rarely) change - at which time you can of course change it the immutable way (create a new one, copying the properties from the old object except for the ones that you want to change).

Minimizing the state of a program is highly beneficial.

Ask them if they want to use a mutable value type in one of your classes for temporary storage from a client class.

If they say yes, ask why? Mutable state doesn't belong in a scenario like this. Forcing them to create the state where it actually belongs and making the statefulness of your data types as explicit as possible are excellent reasons.

share|improve this answer
Foo a = new Foo();
a.setProperty1("asdf");
a.setProperty2("bcde");

If Foo only has two properties, then it's easy to write a constructor that takes two arguments. But suppose you add another property. Then you have to add another constructor:

public Foo(String a, String b, SomethingElse c)

At this point, it's still manageable. But what if there are 10 properties? You don't want a constructor with 10 arguments. You can use the builder pattern to construct instances, but that adds complexity. By this time, you'll be thinking "why didn't I just add setters for all the properties like normal people do"?

share|improve this answer
3  
Is a constructor with ten arguments worse than the NullPointerException that occurs when property7 was not set? Is the builder pattern more complex than the code to check for uninitialized properties in each method? Better to check once when the object is constructed. –  kevin cline Feb 28 '12 at 17:01
2  
As it was said decades ago exactly for this case, "If you have a procedure with ten parameters, you probably missed some." –  9000 Feb 28 '12 at 17:47
    
Why wouldn't you want a constructor with 10 arguments? At what point do you draw the line? I think a constructor with 10 arguments is a small price to pay for the benefits of immutability. Plus, either you have one line with 10 things separated by commas (optionally spread into several lines or even 10 lines, if it looks better), or you have 10 lines anyway as you set up each property individually... –  Ricket Feb 29 '12 at 2:25
1  
@Ricket: Because it increases the risk of putting the arguments in the wrong order. If you're using setters, or the builder pattern, that's pretty unlikely. –  Mike Baranczak Feb 29 '12 at 4:49
4  
If you have a constructor with 10 arguments, perhaps it's time to think about encapsulating those arguments into a class (or classes) of their own and/or taking a critical look at your class design. –  Anna Lear Mar 14 '12 at 1:39

The primary benefit of immutable objects is guaranteeing thread safety. In a world where multiple cores and threads is the norm, this benefit has become very important.

But using mutable objects is very convenient. They perform well, and as long as you're not modifying them from separate threads, and you have a good understanding of what you are doing, they are quite reliable.

share|improve this answer
11  
The benefit of immutable objects is that they are easier to reason about. In multithreaded environment, this is awfully easier; in plain single-threaded algorithms, it is still easier. E.g. you never have to care whether the state is consistent, did the object pass all the mutations needed to be used in a certain context, etc. The best mutable objects allow you to care little about their exact state, too: e.g. caches. –  9000 Feb 28 '12 at 17:44
    
-1, I agree with @9000. Thread safety is secondary (consider objects that appear in immutable but have internal mutable state because of e.g. memoization). Also, bringing up mutable performance is premature optimization, and it's possible to defend anything if you require that the user "know what they're doing". If I knew what I was doing all the time, I'd never write a program with a bug. –  Doval Mar 13 at 19:56
4  
@Doval: There's nothing to disagree about. 9000 is absolutely correct; immutable objects are easier to reason about. That's partly what makes them so useful for concurrent programming. The other part is that you don't have to worry about the state changing. Premature optimization is irrelevant here; the use of immutable objects is about design, not performance, and poor choice of data structures up-front is premature pessimization. –  Robert Harvey Mar 13 at 20:07
    
@RobertHarvey I'm not sure what you mean by "poor choice of data structure up front." There are immutable versions of most mutable data structures out there providing similar performance. If you need a list, and you have a choice of using an immutable list and a mutable list, you go with the immutable one until you know for sure it's a bottleneck in your application and the mutable version will perform better. –  Doval Mar 13 at 20:12
2  
@Doval: I've read Okasaki. Those data structures aren't commonly used unless you're using a language that fully supports the functional paradigm, like Haskell or Lisp. And I dispute the notion that immutable structures are the default choice; the vast majority of business computing systems are still designed around mutable structures (i.e. relational databases). Starting out with immutable data structures is a nice idea, but it's still very ivory tower. –  Robert Harvey Mar 13 at 20:15

Seems like you're approaching it backwards. One should default to immutable. Only make an object mutable if you absolutely have to/just can't make it work as an immutable object.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.