5 ms·
Redux was shit. It made apps less comprehensible and less performant. Immutable state isn't really a great idea for stateful applications, and UI development i
by darksaints 6y ago
Redux was shit. It made apps less comprehensible and less performant.
Immutable state isn't really a great idea for stateful applications, and UI development is an almost purely stateful activity. It can easily be said that any UI is fundamentally a state machine...the state of your UI defines the set of actions that are available to it, and the actions taken define the future state of the UI. This is not just true for web UIs, but all UIs. It is just as true for your blender or transmission lever as it is for your react app. And being a stateful problem, you're far more likely to have to change state than you'll have to change how that state is rendered. This puts redux-style solutions squarely on the wrong side of the expression problem. And the fact that your state is essentially a global variable, using it means you spend vast amounts of time trying to thread constantly changing data types through intricately nested pure functions, and it just fucking sucks.
I'm generally a pure functional programming kind of nerd, but when it comes to difficult inherently stateful programming problems like UI dev, game programming, or simulations, nothing is better than plain old encapsulated state via classes (or maybe actors). Anybody who advocates for pure functional approaches to these types of problems has lost the plot.
- nsonha 6y ago> you're far more likely to have to change state than you'll have to change how that state is rendered. This puts redux-style solutions squarely on the wrong side of the expression problem Could you please elaborate this?
- darksaints 6y agoMaybe, it's a bit hard for me to describe succinctly. Your UI as an application likely has dozens, if not hundreds or thousands of potential states. And the more you develop the feature set of your UI, the more states you will introduce to it. The data that represents these various states is going to constantly evolve to be able to represent them: you'll have evolving business state, evolving widget states, evolving URL states, etc. The expression problem can be summarized as a practical comparison of two types of extensibility: writing functions, which extend through composition, and writing classes, which extend through inheritance. The choice of which one is better starts with asking what is more likely to change: your data or your computation over that data. If you have a problem where your data types are relatively static, but the computations you do on that data are constantly changing, pure functional programming is where it is at. You just write different functions to do different things, and then compose them together to do what you want. This sort of processing is perfect for a ton of usecases...things like data pipelines and etl, machine learning, web services, etc. If you have a problem where your data types are constantly changing but your computation is relatively static, you're going to have a very bad time with a pure functional approach. You'll end up having to edit multiple functions just to change a single data type. When you decide that you no longer want to represent your state with an Array<number> and instead want to represent it with a Set<CustomObject>, you're gonna have to refactor every single function that the original version passed through. And with a massive global state object like Redux, that means not just refactoring the component that renders it, but potentially every single component above it in the HTML tree, modifying them so that they can pass it through to its final destination. That is the sort of burden that happens when you fall on the wrong side of the expression problem. For reference: https://wiki.c2.com/?ExpressionProblem https://wiki.c2.com/?ExpressionProblem
- dwohnitmok 6y ago> It can easily be said that any UI is fundamentally a state machine This doesn't make sense to me as a criticism of Redux. Redux is a giant state machine. That's all it is. Actions are transitions and the store is the current state. The state transition table is the reducer. The Redux architecture (and the Elm architecture that inspired it) is about the purest expression of a state machine you're likely to find in any architecture. The fact that a UI is just a giant state machine is the whole reason these architectures were created in the first place. Redux is tricky and boilerplate-y because of some interactions with React, because it doesn't come with a built-in mechanism for handling interactions with the world "outside" the UI (e.g. interactions with the backend), and because JS doesn't have facilities for immutability out of the box and rather you must bolt on post-hoc solutions.
- darksaints 6y agoThe problem with Redux is two fold: 1. The datastore is a massive global. This already brings to it many of the pitfalls that have caused programmers everywhere to avoid global variables like the plague. But in addition to that, for incredibly complex apps, it is a massive burden to maintain all of your state in one place, without any ability to encapsulate or localize trivial local states. Why do I need a global state tree to determine which option is selected in my select dropdown? Why should I bundle the varying hyperlocalized implications of onChange actions vs onSelect actions with the business implications of things like payment submission states? Why does the state of one button for basic user A have to be bundled in the same data structure as an input element three tabs over, two levels deeper, meant for admin user B with privileged access? 2. Robbed of the concept of benign localized state, all state transitions must be weaved through the entire complex functional tree that renders it. Small refactors of your UI, like moving a widget from one place to a different location in your application "tree", involve not just refactoring the component which renders the widget, but every single component that it passes through, to reroute the data to the right location. It is extremely high touch refactoring, exacerbated by javascript's dynamic nature which is already hard to refactor, and Redux's inability to play nice with static typing tools like Typescript. Redux's bad ideas do not come from the fact that it models a state machine, it comes from the fact that it models it poorly and forces you into using a giant state machine, intricately threaded and tightly coupled throughout your entire application, when smaller state machines are easier to understand and easier to compose. Luckily, there is another programming construct that allows you to easily model state machines, and allows you to build them arbitrarily large or small to meet your demands, and allows you to encapsulate data and actions extremely well so that state and associated actions do not leak. They're called classes.