In my experience, immutable data often reduces the amount of functions with side effects.
Side effects make testing hard, the code hard to understand and error prone.
So I experienced increasing quality with immutable data.
have you seen Object.freeze?
Indeed I didn't, thanks!
It even seems to be supported by typescript as the type definition returns a ReadOnly (stackoverflow.com/questions/486298...).
Makes me wonder why libraries like ngrx don't take advantage of this.
I will definitely try to use that one.
I think difficult testing is a valid counterpoint against mutable data (and side effects in general).
I never experienced decreased code readability though and I see it mentioned a lot. I always wonder if this is something that people say because of some influencers' opinion. I would say that I have a more difficult time following immutable logic as it tends to be longer / more fractured in JS. This is especially true when the involved data is persisting in memory for a longer time.
Edit: Thanks for the comment btw
Regarding mutable data and readability, I think it's fine to have mutable data inside a small and short-lived scope.
The readability issues come when you have mutable data in a large scope, imagine a variable that can get mutated and reassigned at several points in a 100 line function with several levels of indentation, or across multiple function calls. When I read such code, I find it hard to keep track of all the mutations that happened to that variable and its current state.
I understand the pain but I don't think immutability helps in this case.
You have a big chunk of data sitting in the global scope and you have to update it either with mutations or with immutable updates. The difference between the two is that the first case keeps the reference while the latter changes it (it replaces the whole object). The shape of the data changes either way and it's totally okay since it was the goal of the whole snippet.
Manipulating persistent data is a difficult thing to do, probably that's why we have so many state management libs on the (very stateful) modern front-end side.
I honestly think that in this case, it's a draw. Immutability and mutability are both nothing compared to the complex business logic / state structure you work on. Could you provide an example where immutable updates make things clearer when you have to work with data in a large scope?
EDIT: I may have misunderstood you. How do you usually deal with data on the front-end side?
I must say that I lean strongly towards a declarative functional approach in the way I reason about code structure, and I don't often see the need to keep and mutate intermediate data. Depending on your experience and preferences, you might not see the need for immutable data at all.
I like to think about my applications as data flowing through a pipe of transformations. The whole application, as well as any component in it, can be understood as (current_state, input) -> new_state, i.e., it receives the current state and any input that warrants a "change" in the state, and returns an updated version of the state. It does not keep any internal state, and it does not mutate any global state. The intermediate transformations are just output from one part of the application that is sent as input to the next part of the application. In a way, I just think about what input a function needs, what output it produces, and how to compose several functions to apply to the data all the transformations I want.
(current_state, input) -> new_state
In short, I like to keep a copy of the state, send it to the application when there is any input that might change it, then collect the new state that I get at the end, and send that new state to be processed when there is a new input.
Truth be told, writing code with this style in mind is harder than good ol' imperative code. It forces you to put a lot of thought into which parts of the application need what data and how the data will flow there. But I think it's worth the effort because the end result makes following what happens to the data very easy.
I do agree with you that just replacing mutable data structures with immutable ones in the same codebase won't cut it. Moreover, it will probably make things unnecessarily more complex. You need to design and structure your code around the data flow for my approach to work.
Thanks, it's a lot clearer now. I am moderately familiar with Elm and Hyperapp (never used them but read a few articles/docs about them). I use Redux often though which I think is pretty similar (correct me if I am wrong.)
My main concern with this kind of functional front-end pattern is best explained with a short story:
I am a maintaining a transparent reactive state management lib for React (which re-renders comps on relevant data mutations) and a big chunk of the issues are about very basic operations - like getting / settings values or applying (async) side effect. I always explain to simply use obj.prop, obj.prop = value, and async functions which they are all already familiar with. They are too afraid to even try them though because of their functional background.
obj.prop = value
I really like to 'hack around' with the language and I usually feel bad when I am forced into a set of best practices. When I work with immutable libs I often have to check their API for specific things while using mutable data requires me to do this far less often. I can play around a lot more. Obviously, this is not always true but this is my gut feeling.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.