249
votes

If immutable objects¹ are good, simple and offer benefits in concurrent programming why do programmers keep creating mutable objects²?

I have four years of experience in Java programming and as I see it, the first thing people do after creating a class is generate getters and setters in the IDE (thus making it mutable). Is there a lack of awareness or can we get away with using mutable objects in most scenarios?


¹ Immutable object is an object whose state cannot be modified after it is created.
² Mutable object is an object which can be modified after it is created.

23
  • 42
    I think that, apart from legitimate reasons (as mentioned by Péter below), "lazy developer" is a more common reason than "stupid" developer". And before "stupid developer" there's also "uninformed developer". Commented Jun 6, 2012 at 7:58
  • 201
    For every evangelical programmer/blogger there are 1000 avid blog readers that immediately re-invent themselves and adopt the latest techniques. For every one of those there are 10,000 programmers out there with their nose to the grind stone getting a days work done and getting product out the door. Those guys are using tried and trusted techniques that have worked for them for years. They wait until new techniques are widely adopted and show actual benefits before taking them up. Don't call them stupid, and they're anything but lazy, call them "busy" instead. Commented Jun 6, 2012 at 12:21
  • 22
    @BinaryWorrier: immutable objects are hardly a "new thing". They might not have been used heavily for domain objects, but Java and C# had them from the very beginning. Also: "lazy" is not always a bad word, some kinds of "lazy" are an absolute advantage for a developer. Commented Jun 6, 2012 at 13:51
  • 11
    @Joachim: I think it's fairly obvious that "lazy" was used in it's pejorative sense above :) Also, Immutable Objects (like Lambda Calculus, and OOP back in the day - yes I am that old) don't need to be new to suddenly become flavour of the month. I'm not arguing that they're a bad thing (they're not), or that they don't have their place (they obviously do), just go easy on folks because they haven't heard the latest Good Word and been converted as fervently oneself (not blaming you for the "lazy" comment, I know you tried to mitigate it). Commented Jun 6, 2012 at 14:41
  • 116
    -1, immutable objects arent 'good'. Just more or less appropriate for specific situations. Anyone telling you one technique or another is objectively 'good' or 'bad' over another for all situations is selling you religion. Commented Jun 6, 2012 at 20:43

23 Answers 23

324
votes

Both mutable and immutable objects have their own uses, pros and cons.

Immutable objects do indeed make life simpler in many cases. They are especially applicable for value types, where objects don't have an identity so they can be easily replaced. And they can make concurrent programming way safer and cleaner (most of the notoriously hard to find concurrency bugs are ultimately caused by mutable state shared between threads). However, for large and/or complex objects, creating a new copy of the object for every single change can be very costly and/or tedious. And for objects with a distinct identity, changing an existing objects is much more simple and intuitive than creating a new, modified copy of it.

Think about a game character. In games, speed is top priority, so representing your game characters with mutable objects will most likely make your game run significantly faster than an alternative implementation where a new copy of the game character is spawned for every little change.

Moreover, our perception of the real world is inevitably based on mutable objects. When you fill up your car with fuel at the gas station, you perceive it as the same object all along (i.e. its identity is maintained while its state is changing) - not as if the old car with an empty tank got replaced with consecutive new car instances having their tank gradually more and more full. So whenever we are modeling some real-world domain in a program, it is usually more straightforward and easier to implement the domain model using mutable objects to represent real-world entities.

Apart from all these legitimate reasons, alas, the most probable cause why people keep creating mutable objects is inertia of mind, a.k.a. resistance to change. Note that most developers of today have been trained well before immutability (and the containing paradigm, functional programming) became "trendy" in their sphere of influence, and don't keep their knowledge up to date about new tools and methods of our trade - in fact, many of us humans positively resist new ideas and processes. "I have been programming like this for nn years and I don't care about the latest stupid fads!"

20
  • 27
    That's right. Especially in GUI programming, mutable object are very handy. Commented Jun 6, 2012 at 7:56
  • 23
    It's not just resistance, I'm sure lots of devs would love to try out the latest and greatest, but how often do new projects spin up in the average dev's environment where they can apply these new practices? Not everone can or will write a hobby project just to try out immutable state. Commented Jun 6, 2012 at 14:18
  • 29
    Two small caveats to this: (1) Take the moving game character. The Point class in .NET for instance is immutable but creating new points as the result of changes is easy and thus affordable. Animating an immutable character can be made very cheap by decoupling the “moving parts” (but yes, some aspect is then mutable). (2) “large and/or complex objects” can very well be immutable. Strings are often large, and usually benefit from immutability. I once rewrote a complex graph class to be immutable, making the code simpler and more efficient. In such cases, having a mutable builder is the key. Commented Jun 6, 2012 at 14:23
  • 4
    @KonradRudolph, good points, thanks. I did not mean to rule out using immutability in complex objects, but implementing such a class correctly and efficiently is far from being a trivial task, and the extra effort required may not be always justified. Commented Jun 6, 2012 at 14:47
  • 6
    You make a good point about state vs identity. This is why Rich Hickey (author of Clojure) broke the two apart in Clojure. One could argue, that the car you have with 1/2 tank of gas is not the same car as the one with 1/4 tank of gas. They have the same identity, but they are not the same, every "tick" of our reality's time creates a clone of every object in our world, our brains then simply stitch these together with a common identity. Clojure has refs, atoms, agents, etc. to represent time. And maps, vectors and lists for actual time. Commented Jun 6, 2012 at 18:56
130
votes

I think you've all missed the most obvious answer. Most developers create mutable objects because mutability is the default in imperative languages. Most of us have better things to do with our time than to constantly modify code away from the defaults--more correct or not. And immutability is not a panacea any more than any other approach. It makes some things easier but makes others much more difficult as some answers have already pointed out.

8
  • 9
    In most modern IDEs I know, it takes practically the same amount of effort to generate only getters, as to generate both getters and setters. Although it is true that adding final, const etc. takes a bit of extra effort... unless you set up a code template :-) Commented Jun 7, 2012 at 7:19
  • 10
    @PéterTörök it's not just the additional effort--it's the fact that your fellow coders will want to hang you in effigy because they find your coding style so alien to their experience. That also discourages this sort of thing. Commented Jun 7, 2012 at 12:37
  • 5
    That might be overcome with more communication and education, e.g. it is advisable to talk or give a presentation to one's teammates about a new coding style before actually introducing it into an existing codebase. It is true that a good project has a common coding style which is not just an amalgam of the coding styles favoured by every (past and present) project member. So introducing or changing coding idioms should be a team decision. Commented Jun 7, 2012 at 13:08
  • 3
    @PéterTörök In an imperative language mutable objects are the default behavior. If you want only immutable objects, it is best to switch to a functional language.
    – emory
    Commented Jun 8, 2012 at 1:15
  • 3
    @PéterTörök It's a little naive to assume that incorporating immutability into a program involves nothing more than dropping all setters. You still need a way for the state of the program to change incrementally, and for this you need builders, or popsicle immutability, or mutable proxies, all of which take about 1 billion times the effort just dropping the setters took. Commented Aug 1, 2015 at 6:44
49
votes
  1. There is a place for mutability. Domain driven design principles provide a solid understanding of what should be mutable and what should be immutable. If you think about it you will realize it is impractical to conceive of a system in which every change of state to an object requires the destruction and re-composition of it, and to every object that referenced it. With complex systems this could easily lead to completely wiping and rebuilding the entire system's object graph

  2. Most developers don't make anything where the performance requirements are significant enough that they need to focus on concurrency (or a lot of other issues that are universally considered good practice by the informed).

  3. There are some things you simply can't do with immutable objects, like have bidirectional relationships. Once you set an association value on one object, it's identity changes. So, you set the new value on the other object and it changes as well. The problem is the first object's reference is no longer valid, because a new instance has been created to represent the object with the reference. Continuing this would just result in infinite regressions. I did a little case study after reading your question, here's what it looks like. Do you have an alternative approach that allows such functionality while maintaining immutability?

        public class ImmutablePerson { 
    
         public ImmutablePerson(string name, ImmutableEventList eventsToAttend)
         {
              this.name = name;
              this.eventsToAttend = eventsToAttend;
         }
         private string name;
         private ImmutableEventList eventsToAttend;
    
         public string Name { get { return this.name; } }
    
         public ImmutablePerson RSVP(ImmutableEvent immutableEvent){
             // the person is RSVPing an event, thus mutating the state 
             // of the eventsToAttend.  so we need a new person with a reference
             // to the new Event
             ImmutableEvent newEvent = immutableEvent.OnRSVPReceived(this);
             ImmutableEventList newEvents = this.eventsToAttend.Add(newEvent));
             var newSelf = new ImmutablePerson(name, newEvents);
             return newSelf;
         }
        }
    
        public class ImmutableEvent { 
         public ImmutableEvent(DateTime when, ImmutablePersonList peopleAttending, ImmutablePersonList peopleNotAttending){
             this.when = when;     
             this.peopleAttending = peopleAttending;
             this.peopleNotAttending = peopleNotAttending;
         }
         private DateTime when; 
         private ImmutablePersonList peopleAttending;
         private ImmutablePersonList peopleNotAttending;
         public ImmutableEvent OnReschedule(DateTime when){
               return new ImmutableEvent(when,peopleAttending,peopleNotAttending);
         }
         //  notice that this will be an infinite loop, because everytime one counterpart
         //  of the bidirectional relationship is added, its containing object changes
         //  meaning it must re construct a different version of itself to 
         //  represent the mutated state, the other one must update its
         //  reference thereby obsoleting the reference of the first object to it, and 
         //  necessitating recursion
         public ImmutableEvent OnRSVPReceived(ImmutablePerson immutablePerson){
               if(this.peopleAttending.Contains(immutablePerson)) return this;
               ImmutablePersonList attending = this.peopleAttending.Add(immutablePerson);
               ImmutablePersonList notAttending = this.peopleNotAttending.Contains( immutablePerson ) 
                                    ? peopleNotAttending.Remove(immutablePerson)
                                    : peopleNotAttending;
               return new ImmutableEvent(when, attending, notAttending);
         }
        }
        public class ImmutablePersonList
        {
          private ImmutablePerson[] immutablePeople;
          public ImmutablePersonList(ImmutablePerson[] immutablePeople){
              this.immutablePeople = immutablePeople;
          }
          public ImmutablePersonList Add(ImmutablePerson newPerson){
              if(this.Contains(newPerson)) return this;
              ImmutablePerson[] newPeople = new ImmutablePerson[immutablePeople.Length];
              for(var i=0;i<immutablePeople.Length;i++)
                  newPeople[i] = this.immutablePeople[i];
              newPeople[immutablePeople.Length] = newPerson;
          }
          public ImmutablePersonList Remove(ImmutablePerson newPerson){
              if(immutablePeople.IndexOf(newPerson) != -1)
              ImmutablePerson[] newPeople = new ImmutablePerson[immutablePeople.Length-2];
              bool hasPassedRemoval = false;
              for(var i=0;i<immutablePeople.Length;i++)
              {
                 hasPassedRemoval = hasPassedRemoval || immutablePeople[i] == newPerson;
                 newPeople[i] = this.immutablePeople[hasPassedRemoval ? i + 1 : i];
              }
              return new ImmutablePersonList(newPeople);
          }
          public bool Contains(ImmutablePerson immutablePerson){ 
             return this.immutablePeople.IndexOf(immutablePerson) != -1;
          } 
        }
        public class ImmutableEventList
        {
          private ImmutableEvent[] immutableEvents;
          public ImmutableEventList(ImmutableEvent[] immutableEvents){
              this.immutableEvents = immutableEvents;
          }
          public ImmutableEventList Add(ImmutableEvent newEvent){
              if(this.Contains(newEvent)) return this;
              ImmutableEvent[] newEvents= new ImmutableEvent[immutableEvents.Length];
              for(var i=0;i<immutableEvents.Length;i++)
                  newEvents[i] = this.immutableEvents[i];
              newEvents[immutableEvents.Length] = newEvent;
          }
          public ImmutableEventList Remove(ImmutableEvent newEvent){
              if(immutableEvents.IndexOf(newEvent) != -1)
              ImmutableEvent[] newEvents = new ImmutableEvent[immutableEvents.Length-2];
              bool hasPassedRemoval = false;
              for(var i=0;i<immutablePeople.Length;i++)
              {
                 hasPassedRemoval = hasPassedRemoval || immutableEvents[i] == newEvent;
                 newEvents[i] = this.immutableEvents[hasPassedRemoval ? i + 1 : i];
              }
              return new ImmutableEventList(newPeople);
          }
          public bool Contains(ImmutableEvent immutableEvent){ 
             return this.immutableEvent.IndexOf(immutableEvent) != -1;
          } 
        }
    
15
  • 2
    @AndresF., if you have a different take on how to maintain complex graphs with bidirectional relationships using only immutable objects, then I would love to hear it. (I assume we can agree that a collection/array is an object) Commented Jun 7, 2012 at 3:36
  • 2
    @AndresF., (1) My first statement was not universal so it was not false. I actually provided a code example to explain how it was necessarily true in certain cases which happen to be very common in application development. (2) Bidirectional relationships require mutability, in general. I don't believe that Java is the culprit. As I said, I'd be happy to evaluate any constructive alternatives you would suggest, but at this point you're comments sound a lot like "You're wrong because I said so". Commented Jun 7, 2012 at 16:31
  • 14
    @smartcaveman About (2), I also disagree: in general, a "bidirectional relationship" is a mathematical concept orthogonal to mutability. As usually implemented in Java it does require mutability (I agreed with you on that point). However, I can think of an alternative implementation: a Relationship class between the two objects, with a constructor Relationship(a, b); at the point of creating the relationship, both entities a & b already exist, and the relationship itself is also immutable. I'm not saying this approach is practical in Java; just that it's possible.
    – Andres F.
    Commented Jun 7, 2012 at 17:21
  • 4
    @AndresF., So, based on what you're saying, If R is the Relationship(a,b) and both a and b are immutable, neither a nor b would hold a reference to R. For this to work, the reference would have to be stored somewhere else (like a static class). Am I understanding your intention correctly? Commented Jun 7, 2012 at 18:38
  • 9
    It is possible to store a bidirectional relationship for immutable data as Chthulhu points out via laziness. Here is one way to do this: haskell.org/haskellwiki/Tying_the_Knot Commented Aug 24, 2012 at 23:36
36
votes

I've been reading "purely functional data structures", and it's made me realize that there are quite a few data structures that are much easier to implement using mutable objects.

To implement a binary search tree, you have to return a new tree every time: Your new tree will have had to make a copy of each node that has been modified (the un-modified branches are shared). For your insert function this isn't too bad, but for me, things got fairly inefficient quickly when I started to work on delete and re-balance.

The other thing to realize is that you can go years writing object oriented code, and never really realize how terrible shared mutable state can be, if your code isn't run in a way that will expose concurrency problems.

4
  • 3
    Is this the Okasaki book? Commented Jun 7, 2012 at 3:01
  • yep. kinda dry but a ton of good info... Commented Jun 7, 2012 at 13:21
  • 4
    Funny, I always thought Okasakis red/black tree was so much simpler. 10 lines or so. I guess the biggest advantage is when you actually want to keep the old version around as well. Commented Jun 15, 2012 at 13:43
  • While the last sentence has probably been true in the past its not clear that it will remain true in the future, given current hardware trends etc.
    – jk.
    Commented Feb 13, 2014 at 13:42
29
votes

From my point of view, that's a lack of awareness. If you look at other known JVM languages (Scala, Clojure), mutable objects are seen rarely in the code and that's why people start using them in scenarios where single threading is not enough.

I'm currently learning Clojure and have a little experience in Scala (4 years + in Java as well) and your coding style changes because of the awareness of state.

4
  • Perhaps "known" rather than "popular" would be a better choice of word.
    – Den
    Commented Jun 6, 2012 at 8:32
  • Yes, that's right. Commented Jun 6, 2012 at 8:33
  • 5
    +1: I agree: after learning some Scala and Haskell, I tend to use final in Java and const in C++ everywhere. I also use immutable objects if possible and, while mutable objects are still needed very often, it is amazing how often you can use immutable ones.
    – Giorgio
    Commented Aug 17, 2012 at 16:19
  • 5
    I read this comment of mine after two and a half years, and my opinion has changed in favour of immutability. In my current project (which is in Python) we are using mutable objects very very seldom. Even our persistent data is immutable: we create new records as the result of some operations and delete old records when they are not needed any more, but we never update any record on disk. Needless to say, this has made our concurrent, multiuser application much easier to implement and maintain up to now.
    – Giorgio
    Commented Dec 9, 2014 at 21:51
13
votes

I think one major contributing factor has been ignored: Java Beans rely heavily on a specific style of mutating objects, and (especially considering the source) quite a few people seem to take that as a (or even the) canonical example of how all Java should be written.

2
  • 4
    +1, the getter/setter pattern is used way too often as some sort of default implementation after the first data analysis.
    – Jaap
    Commented Jun 7, 2012 at 12:12
  • This is probably a big point ... "because that is how everyone else is doing it" ... so it must be right. For a "Hello World" program it is probably easiest. Managing object state-changes via a slew of mutable properties... that is a little more tricky than the depths of "Hello World" understanding. 20 years later I am very much surprised that the pinnacle of 20th century programming is to write getX and setX methods (how tedious) over every attribute of an object with no structure whatsoever. It is only one step away from directly accessing public properties with 100% mutability. Commented Mar 15, 2013 at 20:53
12
votes

Every enterprise Java system that I've worked on in my career uses either Hibernate or the Java Persistence API (JPA). Hibernate and JPA essentially dictate that your system uses mutable objects, because the whole premise of them is that they detect and save changes to your data objects. For many projects the ease of development that Hibernate brings is more compelling than the benefits of immutable objects.

Obviously mutable objects have been around for much longer than Hibernate, so Hibernate is probably not the original 'cause' of the popularity of mutable objects. Maybe the popularity of mutable objects allowed Hibernate to flourish.

But today if many junior programmers cut their teeth on enterprise systems using Hibernate or another ORM then presumably they'll pick up the habit of using mutable objects. Frameworks like Hibernate may be entrenching the popularity of mutable objects.

1
  • Excellent point. To be all things to all people, such frameworks have little choice but to drop to the lowest common denominator, use reflection based proxies and get/set their way to flexibility. Of course this creates systems with little to no state-transition rules or a common means by which to implement them unfortunately. I am not entirely sure after many projects now what is better for expediency, extensibility and correctness. I tend to think a hybrid. Dynamic ORM goodness but with some definitions for which fields are required and what state changes should be possible. Commented Mar 15, 2013 at 20:57
9
votes

A major point not yet mentioned is that having the state of an object be mutable makes it possible to have the identity of the object which encapsulates that state be immutable.

Many programs are designed to model real-world things which are inherently mutable. Suppose that at 12:51am, some variable AllTrucks holds a reference to object #451, which is the root of a data structure which indicates what cargo is contained in all the trucks of a fleet at that moment (12:51am), and some variable BobsTruck can be used to get a reference to object #24601 points to an object which indicates what cargo is contained in Bob's truck at that moment (12:51am). At 12:52am, some trucks (including Bob's) are loaded and unloaded, and data structures are updated so that AllTrucks will now hold a reference to a data structure which indicates the cargo is in all the trucks as of 12:52am.

What should happen to BobsTruck?

If the 'cargo' property of each truck object is immutable, then object #24601 will forevermore represent the state that Bob's truck had at 12:51am. If BobsTruck holds a direct reference to object #24601, then unless the code which updates AllTrucks also happens to update BobsTruck, it will cease to represent the current state of Bob's truck. Note further that unless BobsTruck is stored in some form of mutable object, the only way that the code which updates AllTrucks could update it would be if the code was explicitly programmed to do so.

If one wants to be able to use BobsTruck to observe the state Bob's truck while still keeping all objects immutable, one could have BobsTruck be an immutable function which, given the value that AllTrucks has or had at any particular time, will yield the state of Bob's truck at that time. One could even have it hold a pair of immutable functions--one of which would be as above, and the other of which would accept a reference to a fleet state and a new truck state, and return a reference to a new fleet state which matched the old, except that Bob's truck would have the new state.

Unfortunately, having to use such a function every time one wants to access the state of Bob's truck could get rather annoying and cumbersome. An alternative approach would be to say that object #24601 will always and forevermore (as long as anyone holds a reference to it) represent the current state of Bob's truck. Code which will want to repeatedly access the current state of Bob's truck wouldn't have to run some time-consuming function every time--it could simply do a lookup function once to find out that object #24601 is Bob's truck, and then simply access that object any time it wants to see the present state of Bob's truck.

Note that the functional approach is not without advantages in a single-threaded environment, or in a multi-threaded environment where threads will mostly just be observing data rather than changing it. Any observer thread which copies the object reference contained in AllTrucks and then examines the truck states represented thereby will see the state of all the trucks as of the moment that it grabbed the reference. Any time an observer thread wants to see newer data, it can just re-grab the reference. On the other hand, having the entire state of the fleet represented by a single immutable object would preclude the possibility of two threads updating different trucks simultaneously, since each thread if left to its own devices would produce a new "fleet state" object which included the new state of its truck and the old states of every other. Correctness may be assured if each each thread uses CompareExchange to update AllTrucks only if it hasn't changed, and responds to a failed CompareExchange by regenerating its state object and retrying the operation, but if more than one thread attempts a simultaneous write operation, performance will generally be worse than if all writing were done on a single thread; the more threads attempt such simultaneous operations, the worse the performance will get.

If individual truck objects are mutable but have immutable identities, the multi-threaded scenario becomes cleaner. Only one thread may be allowed to operate at a time on any given truck, but threads operating on different trucks could do so without interference. While there are ways one could emulate such behavior even when using immutable objects (e.g. one could define the "AllTrucks" objects so that setting state of truck belonging to XXX to SSS would simply require generating an object that said "As of [Time], the state of the truck belonging to [XXX] is now [SSS]; the state of everything else is [Old value of AllTrucks]". Generating such an object would be fast enough that even in the presence of contention, a CompareExchange loop wouldn't take long. On the other hand, using such a data structure would substantially increase the amount of time required to find a particular person's truck. Using mutable objects with immutable identities avoids that problem.

8
votes

There's no right or wrong, it just depends what you prefer. There's a reason why some people prefer languages that favor one paradigm over another, and one data model over another. It just depends on your preference, and on what you want to achieve (and being able to easily use both approaches without alienating die-hard fans of one side or another is a holy grail some languages are seeking after).

I think the best and quickest way to answer your question is for you to head over Pros and Cons of Immutability vs Mutability.

7
votes

Check this blog post: http://www.yegor256.com/2014/06/09/objects-should-be-immutable.html. It summarizes why immutable objects are better than mutable. Here is a short list of arguments:

  • immutable objects are simpler to construct, test, and use
  • truly immutable objects are always thread-safe
  • they help to avoid temporal coupling
  • their usage is side-effect free (no defensive copies)
  • identity mutability problem is avoided
  • they always have failure atomicity
  • they are much easier to cache

People are using mutable objects, as far as I understand, because they are still mixing OOP with imperative procedural programming.

5
votes

In Java immutable objects require a constructor that will take all the properties of the object (or the constructor creates them from other arguments or defaults). Those properties should be marked final.

There are four problems with this mostly having to do with data binding:

  1. Java Constructors reflection meta-data does not retain the argument names.
  2. Java Constructors (and methods) do not have named parameters (also called labels) thus it gets confusing with many parameters.
  3. When inheriting another immutable object proper order of constructors must be called. This can be rather tricky to the point of just giving up and leaving one of the fields non-final.
  4. Most binding technologies (like Spring MVC Data Binding, Hibernate, etc...) will only work with no-arg default constructors (this was because annotations did not always exist).

You can mitigate #1 and #2 using annotations like @ConstructorProperties and creating another mutable builder object (usually fluent) to create the immutable object.

5
votes

Im surprised that no one has mentioned the performance optimization benefits. Depending on the language a compiler can make a bunch of optimizations when dealing with immutable data because it knows the data will never change. All sorts of stuff is skipped over, which gives you tremendous performance benefits.

Also immutable objects almost eliminate the entire class of state bugs.

Its not as big as it should be because its harder, doesn't apply to every language and most people were taught imperative coding.

Also i have found that most programmers are happy in their box and are often resistant to new ideas that they don't completely understand. In general people dont like change.

Also remember, that the state of most programmers is bad. Most programming that is done in the wild is terrible and its caused by a lack of understanding and politics.

4
votes

Why do people use any powerful feature? Why do people use meta-programming, laziness or dynamic typing? The answer is convenience. Mutable state is so easy. It's so easy to update in place and the threshold of project size where immutable state is more productive to work with than mutable state is quite high so the choice won't bite you back for a while.

4
votes

Programming languages are designed for execution by computers. All important building blocks of computers - CPU's, RAM, cache, disks - are mutable. When they aren't (BIOS), they're really immutable and you can't create new immutable objects either.

Hence, any programming language built on top of immutable objects suffers from a representation gap in its implementation. And for early languages such as C, that was a big stumbling block.

1
vote

Without mutable objects you have no state. Admittedly, this is a good thing if you can manage it and if there is any chance an object might be referenced from more than one thread. But the program is going to be rather boring. A lot of software, particularly web servers, avoids taking responsibility for mutable objects by pushing mutability off on databases, operating systems, system libraries, etc. As a practical matter, this does free the programmer from mutability problems and makes web (and other) development affordable. But the mutability is still there.

In general, you have three types of classes: normal, non-thread-safe classes, that have to be carefully guarded and protected; immutable classes, which can be used freely; and mutable, thread-safe classes that can be used freely but which must be written with extreme care. The first type is the troublesome one, with the worst ones being those that are thought to be of the third type. Of course, the first type are the easy ones to write.

I usually end up with lots of normal, mutable classes that I have to watch very carefully. In a multi-thread situation, the synchronization necessary slows everything down even when I can avoid a deadly embrace. So I'm ususally making immutable copies of the mutable class and handing those off to whoever can use it. A new immutable copy is needed every time the orignal mutates, so I imagine at times I may have a hundred copies of the original out there. I'm utterly dependent on Garbage Collection.

In summary, non-thread-safe, mutable objects are fine if you are not using multiple threads. (But multithreading is inflitrating everywhere--be careful!) They can be used safely otherwise if you restrict them to local variables or rigorously synchronize them. If you can avoid them by using other people's proven code (DBs, system calls, etc.) do so. If you can use an immutable class, do so. And I think, in general, people are either unaware of multithreading problems or are (sensibly) terrified of them and using all kinds of tricks to avoid multithreading (or rather, pushing responsibility for it elsewhere).

As a P.S., I sense that Java getters and setters are getting out of hand. Check this out.

2
  • 7
    Immutable state is still state.
    – Jeremy
    Commented Jun 6, 2012 at 22:01
  • 3
    @JeremyHeiler: True, but it's the state of something that is mutable. If nothing mutates, there is only one state, which is the same thing as no state at all. Commented Jun 7, 2012 at 20:07
1
vote

Lots of people had good answers so I want to point out something you touched on that was very observant and extremely true and hasn't been mentioned elsewhere here.

Automatically creating setters and getters is a horrible, horrible idea, yet it's the first way procedural-minded people try to force OO into their mindset. Setters and getters, along with properties should only be created when you find you need them and not everyby default

In fact although you need getters pretty regularly, the only way setters or writable properties should ever exist in your code is through a builder pattern where they are locked down after the object has been completely instantiated.

Many classes are mutable after creation which is fine, it just shouldn't have it's properties directly manipulated--instead it should be asked to manipulate it's properties through method calls with actual business logic in them (Yes, a setter is pretty much the same thing as directly manipulating the property)

Now this doesn't really apply to "Scripting" style code/languages either but to code you create for someone else and expect others to read repeatedly over the years. I've had to start making that distinction lately because I enjoy messing with Groovy so much and there is a huge difference in targets.

1
vote

Mutable objects are used when you have to set multiples values after instantiating the object.

You shouldn't have a constructor with, say, six parameters. Instead you modify the object with setter methods.

An example of this is a Report object, with setters for font, orientation etc.

For short: mutables are useful when you have a lot of state to set to an object and it would not be practical to have a very long constructor signature.

EDIT: Builder pattern can be used build the whole state of the object.

10
  • 3
    this is presented as if mutability and changes after instantiation is the only way to set multiple values. For the sake of completeness note that Builder pattern offers equal or even more powerful capabilities and doesn't require one to sacrifice immutability. new ReportBuilder().font("Arial").orientation("landscape").build()
    – gnat
    Commented Aug 17, 2012 at 13:12
  • 1
    "It would not be practical to have a very long constructor signature.": You can always group parameters into smaller objects and pass these objects as parameters to the constructor.
    – Giorgio
    Commented Aug 17, 2012 at 18:08
  • 1
    @cHao What if you want to set 10 or 15 attributes? Also it doesn't seem good that a method named withFont returns a Report. Commented Dec 27, 2012 at 17:10
  • 1
    As far as setting 10 or 15 attributes, the code to do so wouldn't be awkward if (1) Java knew how to elide the construction of all those intermediate objects, and if (2) again, names were standardized. It's not a problem with immutability; it's a problem with Java not knowing how to do it well.
    – cHao
    Commented Dec 27, 2012 at 17:44
  • 1
    @cHao Making a call chain for 20 attributes is ugly. Ugly code tends to be poor quality code. Commented Dec 27, 2012 at 17:45
1
vote

I think using mutable objects stems from imperative thinking: you compute a result by changing the content of mutable variables step by step (computation by side effect).

If you think functionally, you want to have immutable state and represent subsequent states of a system by applying functions and creating new values from old ones.

The functional approach can be cleaner and more robust, but it can be very inefficient because of copying, so that you want to fall back to a shared data structure that you modify incrementally.

The trade-off that I find most reasonable is: Start with immutable objects and then switch to mutable ones if your implementation is not fast enough. From this point of view, using mutable objects systematically from the beginning can be considered some kind of premature optimization: you choose the more efficient (but also more difficult to understand and to debug) implementation from the beginning.

So, why do many programmers use mutable objects? IMHO for two reasons:

  1. Many programers have learnt how to program using an imperative (procedural or object-oriented) paradigm, therefore mutability is their basic approach to defining computation, i.e. they do not know when and how to use immutability because they are not familiar with it.
  2. Many programmers worry about performance too early whereas it is often more effective to first focus on writing a program that is functionally correct, and then try to find bottlenecks and optimize it.
11
  • 1
    The issue is not just speed. There are many types of useful constructs which simply cannot be implemented without using mutable types. Among other things, communication between two threads requires that, at absolute minimum, both must have a reference to a shared object which one can put data and the other can read it. Further, it is often semantically much clearer to say "Change properties P and Q of this object" than to say "Take this object, construct a new object which is just like it except for the value of P, and then a new object which is just like that except for Q".
    – supercat
    Commented Aug 22, 2012 at 22:55
  • 1
    I am not a FP expert but AFAIK (1) thread communication can be achieved by creating an immutable value in one thread and reading it in another (again, AFAIK, this is the Erlang approach) (2) AFAIK the notation for setting a property does not change much (e.g. in Haskell setProperty record value corresponds to Java record.setProperty(value)), only the semantics changes because the result of setting a property is a new immutable record.
    – Giorgio
    Commented Aug 22, 2012 at 23:07
  • 1
    "both must have a reference to a shared object which one can put data and the other can read it": more precisely, you can make an object immutable (all members const in C++ or final in Java) and set all the content in the constructor. Then this immutable object is handed-over from the producer thread to the consumer thread.
    – Giorgio
    Commented Aug 22, 2012 at 23:12
  • 1
    (2) I have already listed performance as a reason not to use immutable state. Regarding (1), of course the mechanism that implements the communication between threads needs some mutable state, but you can hide this from your programming model, see e.g. the actor model (en.wikipedia.org/wiki/Actor_model). So even if at a lower level you need mutability to implement the communication, you can have an upper abstraction level in which you communicate between threads sending immutable objects back and forth.
    – Giorgio
    Commented Aug 22, 2012 at 23:21
  • 1
    I am not sure I understand you fully, but even a pure functional language where every value is immutable, there is one mutable thing: the program state, i.e. the current program stack and variable bindings. But this is the execution environment. Anyway, I suggest that we discuss this in chat some time and then clean up the messages from this question.
    – Giorgio
    Commented Aug 23, 2012 at 16:04
1
vote

I know you are asking about Java, but I use mutable vs immutable all the time in objective-c. There is a immutable array NSArray, and a mutable array NSMutableArray. These are two different classes written specifically in an optimized way to handle the exact use. If I need to create an array and never alter it's contents, I'd use NSArray, which is a smaller object and is much faster at what it does, compared to a mutable array.

So if you create a Person object that is immutable then you only need a constructor and getters, thus the object will be smaller and use less memory, which in turn will make your program actually faster. If you need to change the object after creation then a mutable Person object will be better so that it can change the values instead of creating a new object.

So: depending on what you plan on doing with the object, choosing mutable vs immutable can make a huge difference, when it comes to performance.

1
vote

Additional to many other reasons given here, a problem is that mainstream languages do not support immutability well. At least, you are penalized for immutability in that you have to add additional keywords like const or final, and have to use illegible constructors with many, many arguments or code lengthy builder patterns.

That's much easier in languages made with immutability in mind. Consider this Scala snippet for defining a class Person, optionally with named arguments, and creating a copy with a changed attribute:

case class Person(id: String, firstName: String, lastName: String)

val joe = Person("123", "Joe", "Doe")
val spouse = Person(id = "124", firstName = "Mary", lastName = "Moe")
val joeMarried = joe.copy(lastName = "Doe-Moe")

So, if you want developers to adopt immutability, this is one of the reasons why you might consider switching to a more modern programming language.

3
  • this doesn't seem to add anything substantial over points made and explained in prior 24 answers
    – gnat
    Commented Dec 9, 2014 at 8:13
  • @gnat Which of the previous answers makes the point that most mainstream languages do not decently support immutability? I think that point simply has not been made (I checked), but this is IMHO a quite important obstacle. Commented Dec 9, 2014 at 20:10
  • this one for example goes in depth explaining this issue in Java. And at least 3 other answers indirectly relate to it
    – gnat
    Commented Dec 9, 2014 at 20:28
0
votes

Immutable means you can't change the value, and mutable means you can change the value if you think in terms of primitives, and objects. Objects are different than primitives in Java in that they are built in types. Primitives are built in types like int, boolean, and void.

A lot of people people think that primitives and objects variables that have a final modifier infront of them are immutable, however, this isn't exactly true. So final almost doesn't mean immutable for variables. Check out this link for a code sample:

public abstract class FinalBase {

    private final int variable; // Unset

    /* if final really means immutable than
     * I shouldn't be able to set the variable
     * but I can.
     */
    public FinalBase(int variable) { 
        this.variable = variable;
    }

    public int getVariable() {
        return variable;
    }

    public abstract void method();
}

// This is not fully necessary for this example
// but helps you see how to set the final value 
// in a sub class.
public class FinalSubclass extends FinalBase {

    public FinalSubclass(int variable) {
        super(variable);
    }

    @Override
    public void method() {
        System.out.println( getVariable() );
    }

    @Override
    public int getVariable() {

        return super.getVariable();
    }

    public static void main(String[] args) {
        FinalSubclass subclass = new FinalSubclass(10);
        subclass.method();
    }
}
-1
votes

I think a good reason would be to model "real-life" mutable "objects", like interface windows. I vaguely remember having read that the OOP was invented when somebody tried to write software to control some cargo port operation.

1
  • 1
    I cannot find yet where i've read this about the origins of OOP, but according to Wikipedia, some Integrated Regional Information System of a large container shipping company OOCL is written in Smalltalk.
    – Alexey
    Commented Jan 1, 2014 at 9:55
-2
votes

Java, in many cases mandates mutable objects, eg when you want to count or return something in a visitor or runnable, you need final variables, even without multithreading.

6
  • 5
    final is actually about 1/4 of a step towards immutability. Not seeing why you mention it.
    – cHao
    Commented Jun 7, 2012 at 4:11
  • did you actually read my post?
    – Ralf H
    Commented Dec 23, 2012 at 18:16
  • Did you actually read the question? :) It had absolutely nothing to do with final. Bringing it up in this context conjures a really weird conflation of final with "mutable", when the very point of final is to prevent certain kinds of mutation. (BTW, not my downvote.)
    – cHao
    Commented Dec 23, 2012 at 19:45
  • I'm not saying you don't have a valid point in here somewhere. I'm saying you're not explaining it very well. I sorta semi see where you're probably going with it, but you need to go further. As is, it just looks confused.
    – cHao
    Commented Dec 23, 2012 at 19:59
  • 1
    There are actually very few cases where a mutable object is required. There are cases where the code would be clearer, or in some cases faster, by using mutable objects. But consider that the vast majority of design patterns are basically just a half-assed rendition of functional programming for languages that don't natively support it. Fun part of that is, FP only requires mutability in very select places (namely, where side effects must occur), and those places are generally tightly limited in number, size, and scope.
    – cHao
    Commented Dec 27, 2012 at 15:32

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