Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do effectively immutable objects make sense?

In the book Java Concurrency In Practice it explains the advantages of "effectively immutable" objects versus mutable objects concurrency-wise. But it does not explain what advantage "effectively immutables" objects would offer over really immutable objects.

And I don't get it: can't you always build a really immutable object at the moment you'd decide to publish safely an "effectively immutable" object? (instead of doing your "safe publication" you'd build a really immutable object and that's it)

When I'm designing classes I fail to see cases where I couldn't always build a truly immutable object (using delegation if needed etc. to build other wrapped objects, themselves truly immmutable of course) at the moment I'd decide to "safely publish".

So are "effectively immutable" object and their "safe publication" just a case of bad design or poor APIs?

Where would you be forced to use an effectively immutable object and be forced to safely publish it where you couldn't build a much superior really immutable object?

like image 559
NoozNooz42 Avatar asked Jan 03 '12 02:01

NoozNooz42


People also ask

Should you use immutable objects?

Immutable objects offer a number of advantages for building reliable applications. As we don't need to write defensive or protective code to keep application state consistent, our code can be simpler, more concise, and less error-prone than when we define mutable objects.

In which situations is it better to use an immutable object?

Immutable objects can be useful in multi-threaded applications. Multiple threads can act on data represented by immutable objects without concern of the data being changed by other threads. Immutable objects are therefore considered more thread-safe than mutable objects.

Why would you want an immutable object?

Immutable objects don't change their internal state in time, they are thread-safe and side-effects free. Because of those properties, immutable objects are also especially useful when dealing with multi-thread environments. You can find the examples used in this article over on GitHub.

Why is immutability a good thing?

Besides reduced memory usage, immutability allows you to optimize your application by making use of reference- and value equality. This makes it really easy to see if anything has changed. For example a state change in a react component.


3 Answers

Yes, they make sense in some cases. An easy example is when you want some property to be generated lazily and cached so you can avoid the overhead of generating it if it's never accessed. String is an example of an effectively immutable class that does this (with its hashcode).

like image 146
ColinD Avatar answered Oct 20 '22 14:10

ColinD


For circular immutables:

class Foo
{
    final Object param;
    final Foo other;

    Foo(Object param, Foo other)
    {
        this.param = param;
        this.other = other;
    }

    // create a pair of Foo's, A=this, B=other
    Foo(Object paramA, Object paramB)
    {
        this.param = paramA;
        this.other = new Foo(paramB, this);
    }

    Foo getOther(){ return other; }
}



// usage
Foo fooA = new Foo(paramA, paramB);
Foo fooB = fooA.getOther();
// publish fooA/fooB (unsafely)

A question is, since this of fooA is leaked inside constructor, is fooA still a thread safe immutable? That is, if another thread reads fooB.getOther().param, is it guaranteed to see paramA? The answer is yes, since this is not leaked to another thread before the freeze action; we can establish hb/dc/mc orders required by spec to prove that paramA is the only visible value for the read.

Back to your original question. In practice there are always constraints beyond the pure technical ones. Initialize everything inside constructor is not necessarily the best option for a design, considering all engineering, operational, political and other human-ish reasons.

Ever wondering why we are fed to think that it is a great supreme idea?

The deeper problem is Java lacks a general cheap fense for safe publication which is cheaper than volatile. Java only has it for final fields; for some reason, that fence is not available otherwise.

Now final carries two independent meanings: 1st, that a final field must be assigned exactly once; 2nd, the memory semantics of safe publication. These two meanings have nothing to do with each other. It is quite confusing to bundle them together. When people need the 2nd meaning, they are forced to accept the 1st meaning too. When the 1st is very inconvenient to achieve in a design, people wonder what they have done wrong - not realizing that it's Java that did wrong.

Bundling of two meanings under one final makes it double plus good, so that apparently we have more reason and motivation to use final. The more sinister story is actually we are forced to use it because we are not given a more flexible choice.

like image 45
irreputable Avatar answered Oct 20 '22 15:10

irreputable


Using effectively immutable objects lets you avoid creating a considerable number of classes. Instead of making pairs of [mutable builder]/[immutable object] classes, you can build one effectively immutable class. I usually define an immutable interface, and a mutable class that implements this interface. An object is configured through its mutable class methods, and then published through its immutable interface. As long as the clients of your library program to the interface, to them your objects remain immutable through their published lifetime.

like image 1
Sergey Kalinichenko Avatar answered Oct 20 '22 15:10

Sergey Kalinichenko