If immutable objects are good, why do people keep creating mutable objects?

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

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

    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.

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

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

    By the way, it's not "getters" and "setters" that make an object mutable or not. Public member variables can be modified without getters and setters--and that makes an object mutable.

    Don't call them lazy. I am lazy. I make my classes immutable (usually), because it increases my chance of getting it right first time, and I can't be bothered with debugging. Yes busy is the word, very busy.

    BTW - even if we ignore the whole mutability vs immutability issue, public getters and setters are a well known source of pain in OO design, since they tend to break encapsulation and invariants.

    one reason: convenience

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

    Why are immutable objects good?

    Why do people keep using the Java language at all, if it is on one hand ridiculously uncompromising about "good style" of pure OO but does very little to even encourage style decisions that would _really_ be useful, such as not using mutable state?

    @GrandmasterB read "if" as "given that" and you don't need to be offended by the opening of the question ;-)

    In iOS objective-C, array = [array arraywithobject:] performance sucks... So immutable for performance.

    @leftaroundabout I use Java because it works. It's not the latest fashion, but it works.

    What's the point in objects if everything is immutable? Use proper functional languages instead.

    Immutable vs mutable is failure to recognize the real problem IMO which is an excess of objects mutating other objects.

    Of course if you design your objects to just be data-classes then I guess immutable is a "good-thing". However, good OO designs generally don't design their classes to just be data-classes. Thus, I really wonder about the types of designs coming out of people that make extensive use of immutable objects.

    Just a bit related to Immutability. But getters and setters is a direct violation of Encapsulation which is the main principle of OOP. This takes the responsibility of the state of the data away from the Object/Class which pretty much defeats the purpose of OOP.

    Mutable objects aren't bad. The problem is that they are often abused and handled irresponsibly. It does irk me a little when I run across a method that returns a value and edits the mutable parameters with zero documentation. (what happened to the single responsibility principle).

    @GrandmasterB - Could you please give some examples for situations where immutable are more appropriate ?

    Immutable is best for 5% of stuff, mutable is best for 5% of stuff, and the other 90% of the time these objects aren't being used it ways where it matters either way. Therefore since mutable is default it takes that 90%. So 95% is mutable...which is about what most programmers do. Most people don't treat trends as religions...we just use them where they're useful.

    @andho - ...that's 100% incorrect. Getters and setters are actually, literally, what makes encapsulation in OOP by abstracting away the internal changes to the external accessors/mutators (i.e. getters/setters). Read up on OOP: http://codebetter.com/raymondlewallen/2005/07/19/4-major-principles-of-object-oriented-programming/

    @JimboJonny if implemented correctly yes. But in context of a Java Bean, any other object is able to manipulate the data the class is responsible for and allows invalidating the invariants of the object. This style is okay for Anemic Domains, but then they are just data structures. All setters are mutators but not all mutators are setters. If you implement mutators as command methods, the classes will become more descriptive and more appropriate to the essence of OOP. The problem is most of the time, the classes not having any behaviour/logic except setting and getting values.

  • 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!"

    That's right. Especially in GUI programming, mutable object are very handy.

    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.

    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.

    @SnOrfus, good point, I should add that resistance may come from the organization as well. Luckily, we can always look for a better workplace :-)

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

    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.

    Even more than simply moving a character around, imagine a particle effect system. Imagine the cost in time and memory to instantiate hundreds, possibly thousands of new particle objects 60 times per second. Mutable particles, with mutable world positions have a tremendous performance advantage.

    As of speed - the compiler could optimize it out so the immutable object are mutable behind scene and/or reason about the code enabling further optimalisation. Of course it does not mean it do. @scriptocalypse: One could argue that if you mutate all of the state that make no difference performance-wise. If the 'objects' are large arrays then computation usually IS non-destructive(code writes into different region of memory the it reads from) - for example on GPUs. Which makes the particle systems probably a bad example.

    @TimothyBaldridge, fair enough, "you can't step twice into the same stream", stated Heraclitus more than 2K years ago :-)

    @KonradRudolph: The `Point` structure in .net exposes its fields and thus allows them to be mutated by anything which has access to *the storage location holding the `Point` which contains them*. Note that the fields of all non-trivial structs stored in mutable storage locations are mutable (even if only by doing an all-field-copy assignment), and the fields of all structs stored in immutable storage locations are immutable.

    @supercat Ouch, my mistake. Still, I think that it *could* have been just as well been made immutable.

    "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": I find this a bit strange though: FP languages have been around for more than 40 years and are quite common in Computer Science curricula. My main education was with procedural and object-oriented programming languages but I had to learn about Lisp, lambda calculus, etc, so now the switch to FP is not that hard. So I do not totally understand this inertia and this difficulty to think in a different paradigm.

    @Giorgio, when did you study CS? I graduated in 1994 and our curricula contained none of FP nor lambda calculus, although it was math / theory heavy. Fair enough, my country was not and is not at the cutting edge regarding IT and CS, so it may be that FP was more well known in the academia of other parts of the world even back then.

    @Péter Török: I graduated in 1993 in Italy. We had one course on computability, covering lambda calculus, and one general course on programming languages, covering the principles of procedural, object-oriented, functional, and logic programming languages. I did one project in Prolog and also played a bit with Lisp at that time. We also learnt about denotational semantics, which is also based on composing functions and often uses the lambda notation.

    @FlorianSalihovic, ever heard of functional reactive programming?

    +1 for *where objects don't have an identity*. Making up efficient reference-able identity was mostly impossible to me. I still want a trick to solve it.

    Well, if you consider gas in fuel tank is apart, you don't need to recreate the car and you can still keep most things immutable.

    "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." Generally true in most languages, but Clojure (and the genius of Rich Hickey) specifically seems to alleviate this concern by implementing persistent data structures.

    @KonradRudolph It would be cool if languages allowed you to speak of 'values' and 'objects', and the compiler/interpreter would work out when it is appropriate (taking into account correctness and efficiency) to copy the data vs referencing it.

    Immutability is now being embraced in "GUI", especially in the Web. See Redux, ImmutableJS, Rx, and the like.

License under CC-BY-SA with attribution

Content dated before 6/26/2020 9:53 AM