DEV Community

Discussion on: What Do You Think About Immutable Data?

Collapse
 
avalander profile image
Avalander • Edited

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.

Thread Thread
 
solkimicreb profile image
Miklos Bertalan • Edited

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?

Thread Thread
 
avalander profile image
Avalander • Edited

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.

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.

More specific to the frontend side, I really like the Elm architecture, and I use Hyperapp a lot. It's basically the Elm architecture adapted to Javascript, and it is a really simple and powerful framework.

Thread Thread
 
solkimicreb profile image
Miklos Bertalan

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.

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.