[LRUG] The advantage of immutability?

Tejas Dinkar tejasdinkar at gmail.com
Wed Sep 9 08:49:13 PDT 2015


There is actually two other benefits, but which I think has been implied by other answers, but I thought I’ll elaborate here. These are benefits of pushing immutability into lower layers, and capturing the mutability at a higher level.

Easier to detect change

React(JS) does this pretty heavily. If you have an component with component.state, it’s really hard to detect when someone changes component.state.foo.bar = “new-value”. Instead of this, it’s much easier to ask that your caller replaces the entire value of component.state.

And since the original map was not altered, it’s possible to basically do something like this
function setState(newState) {
  oldState = this.state;
  diff fancyDiffAlgorithm(oldState, newState);
  onlyUpdateThePartsOfThePage(diff)
}

Safer access of the object across threads. 

It’s hard to give a good example, but say you had a global map, “state” with one field “counters”.
global.state[“counters”] = 0

The following statement could not run on multiple threads at once:
global.state[“counters”] = global.state[“counters”] + 1 

However, if your language exposes a primitive like the compare and swap, and you can immutably “replace" your map, if you write your program as follows

# Pseudo code, though I believe there is a ruby library that implements this
compare_and_swap(global.state) { |x| x.merge({“counters”: x[“counters”] + 1})} # Explaining this further in [1]

[1] For people unfamiliar, compare and swap is a concurrency pattern, mostly resembling the following pseudocode
old = x
new = f(old)

# next four lines done atomically
if (x is still == old)
  x = new
else
  retry until we pass

The condition is obviously that f(x) must be a pure function, as it runs possibly multiple times until it’s successful. This means it cannot mess up “x”, as other threads may be executing f(x) concurrently.

On 9 September 2015 at 8:55:32 pm, Jonathon Horsman (jonathon at arctickiwi.com) wrote:

Hey thanks for the responses.

To summarise the main reason appears to be to avoid unexpected changes being made on an object as it is passed around.

I'm struggling a bit to envisage when this might occur in the relatively simple sorts of apps I'm working on.

In your experience what sorts of instances has this happened? Logging was mentioned which to me seems extremely unlikely that a logger would mutate an object.
If it does surely that's a major bug in the logger or a failure of the tests to pick that up?

In the simple case of say a user in the system updating their email address. They'd have a form which would make a put request to /users/1234
The process to handle that update in an immutable system would be either:

Update email address of user with ID 1234
Update first name of user with ID 1234
Update last name of user with ID 1234
etc...

OR:

Read existing user 1234 from database
Merge new (changed) attributes and unchanged attributes the user doesn't have permission to change, e.g. creation date.
Create a new user object with the merged attributes
Persist new object (with same ID) to database
Pass back new object to caller to be rendered

Also in this example the mutability would be useful - the caller wants to have the modified object since that's the up-to-date representation.

Roland your suggestion to create another object would fit in certain cases where you're maintaining a sort of event log of activity, but there are many (most) instances where you need to update a value in a data store rather than provide a sort of versioning. Sorry if I've misunderstood your suggestion.

Thanks again for your responses.

On 9 September 2015 at 11:43, Roland Swingler <roland.swingler at gmail.com> wrote:
> why an immutable object is an advantage

In general immutability is nice because a lot, lot less can go wrong with immutable objects. A lot of bugs are caused by editing state incorrectly - if you can't change the state of an object then a whole class of bugs vanish by design.

In terms of your specific problem a way to approach it might be - you have a Request of some form - instead of changing state model what is going on - so create a Response model (almost certainly a better name - I don't know your problem beyond what you've told us) with a state field of denied. To deny a request, create a Response object set to denied.

This gives you some nice properties - you can start doing things like recording like when the request was denied, who denied it etc. if you like; also if a request is denied by mistake for then you can just create a new Response and you have a history of all the state changes.

Now, none of this may be practical in your application (for example if lots of other things are already coupled to a mutable state field on your Request). In which case do whatever is simplest.

Thanks,
Roland

On Wed, Sep 9, 2015 at 11:25 AM, Jonathon Horsman <jonathon at arctickiwi.com> wrote:
Hey smart people

Can you shed some light on why an immutable object is an advantage for a web-based Ruby app?

For example this app I'm working on has these Request things and a user has the ability to deny a Request.

So the user would click a button which performs a post to the Request controller's deny action.
If I were using Rails or some non-immutable based system I would fetch the object from the database, set it's status to denied, and save it.

However since this Request is an immutable object, I have to either:

1. Write an update_status method which sets that value in the database, which becomes tedious when there's lots of possible attribute update combinations
or
2. Read the object from the database, copy all the values to a new object with the denied status, and stick that back into the database. Seems like pointless overhead and could be dangerous if later that object gets another attribute which I forget to copy.

My knowledge of immutable objects originates with Java Strings which I understand makes sense for performance and memory management reasons.
I don't think this applies here though?

Thanks!

Jonno

_______________________________________________
Chat mailing list
Chat at lists.lrug.org
Archives: http://lists.lrug.org/pipermail/chat-lrug.org
Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org
List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org



_______________________________________________
Chat mailing list
Chat at lists.lrug.org
Archives: http://lists.lrug.org/pipermail/chat-lrug.org
Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org
List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org


_______________________________________________  
Chat mailing list  
Chat at lists.lrug.org  
Archives: http://lists.lrug.org/pipermail/chat-lrug.org  
Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org  
List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org  
-- 
Tejas Dinkar
Quintype
ph: +91 98455 72696
skype: tdinkar
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20150909/0e91e568/attachment.html>


More information about the Chat mailing list