Hacker News new | ask | show | jobs
by qwtel 1126 days ago
In my view it's the other way around. If you stick to a state machine for your app logic, you'll end up with an unintentional half built reimplementation of a general purpose programming language.

The fact these state machines aren't the mathematical constructs from CS, but "extended" versions with "context" (this is where all the actual app state goes), should be the giveaway that they aren't a sufficiently capable model for the demands of UI programming. After you add extensions for every possible need, what do you end up with?

I understand the appeal though. UI development is a complicated mess, and people want a formula to make sense of it all. I've went through several iterations of these cookie cutter patterns form MVC to MVVMC++ to flux to redux to redux-saga to immutable.js to Recoil and so on. At best these marginally improve the situation, at worst they end up adding complexity on top of the inherent mess.

At the risk of missing out on the One True Way of doing UI development, I'll pass on this latest installment. I keep open the possibility that state machines "marginally improve the situation" though.

5 comments

With Vue and Pinia, one doesn't even have to bother with patterns. Frankly, I think Redux does more harm than good. Their borderline incomprehensible documentation is a testament to that.
Hi, I maintain Redux and wrote most of our docs (including our current tutorials).

Can you give some details on which parts of our docs you feel are "incomprehensible"? I'm curious which specific pages you've been looking at, and for what purpose.

We've tried to organize the docs using the "Documentation System" approach described at [0]: Tutorials for teaching step-by-step, Explanations and How-To guides for specific topics, and References for API details.

Generally we want people to go through our "Redux Essentials" tutorial [1] as the primary way to learn how to use Redux correctly. It teaches "modern Redux" patterns with Redux Toolkit as the standard way to write Redux logic (including RTK Query for handling data fetching), and React-Redux hooks in components.

I'm genuinely interested in feedback on what explanations aren't clear and how we can improve things!

[0] https://documentation.divio.com/

[1] https://redux.js.org/tutorials/essentials/part-1-overview-co...

There you are.
Redux shines when you have an actual "app" with a large dynamic "global" client-bound state that pops up in different places and needs undo/redo (Like a video editor, Blender,etc). And even then you preferably need some small helpers to make the experience smoother (slices from redux toolkit is a good example).

For most people doing a small CRUD pages that's just woefully overkill.

Some people are really creative at creating dozens of boolean flags with lots of possible and impossible combinations. And some don't even correspond to screen in your figma file from designer (but can actually happen due to race condition... etc). You will really want a state machine that just list every possible state and transition in that case.
State management using redux (ngrx flavor) is the best way of managing application state I have discovered so far.

Simple structure, powerful, what do you want more?

I agree with you, the “extended” version of state machines with “context” is the problem with xstate. Modelling state transitions deterministically is great, but context and actions are too closely coupled to machine transitions, making it very hard to write generic or reusable state machines when you actually make use of these features. Had xstate focused on only transitions (like regular FSMs) and left context/data and actions/effects to other application-level abstractions, xstate would be widely compatible with many projects instead of requiring a heavy-duty paradigm shift in terms of how you model your application logic.
I agree that state machines alone are probably not sufficient, but they are frequently a useful way of modelling at least part of the interaction flow. Honestly they should probably be used more in all areas of programming (but they should not be used exclusively).
I think the sweet spot are state machines that don't take "context" as inputs but have richer effects in their transitions (if we're talking about Mealy Machines).

This way, the internal behavior of the machine is still deterministic and easy to reason about.

I found this tiny two lines in the erlang state machine docs that I've kept around for years because it's such a precise definition of how they need to work in practice:

"State(S) x Event(E) -> Actions (A), State(S')"

"If we are in state S and the event E occurs, we should perform the actions A and make a transition to the state S'."

The fn needs to yield both the new state and a collection of side effects of that transition that need to be handled somehow. You'll need side effects no matter what so might as well formally describe them in the SM, then handle them outside of it in a way that fits the language/framework/runtime. I think this is basically exactly what elm does and how a couple of the redux extensions work too.

I am too looking for a solution to make UI development easier to understand and less complicated. I am working on a state machine formulation too.

I've worked on MVVM and redux. GUIs end up complicated and difficult to understand if you're not familiar with the codebase.

The problem is that UI is complicated. It’s all edge cases and human factors.
While that's true, there are also limitations and gotchas of Web based UIs that make state management very complex and messy. There are layouts that you _cannot_ express (with HTML/CSS/JS) without intermediate rendering steps and the whole paradigm of separating state and representation (React etc.) falls apart very quickly.

And before anyone asks: Yes, this comes up surprisingly often. Yes, alternatives have always been explored first. Yes, I'm up to date with browser capabilities. No, you can't say "no" to these designs when you're hired specifically because you can make things work.

Example of such a layout?
Do other UI building paradigms solve these issues more comfortably, whilst retaining (comfortable-ish hooks into) accessibility?