7 ms·
The fundamental challenge of GUIs is that they have state as a core concern. Unlike most systems, state is not an implementation detail that can be refactored a
by brundolf 6y ago
The fundamental challenge of GUIs is that they have state as a core concern. Unlike most systems, state is not an implementation detail that can be refactored away. It is central to the problem domain. The end user sees and cares about having a stateful system.
The hardest part of dealing with state in a complex system is maintaining consistency in different places. Some instances of this this can be avoided by creating single-sources-of-truth, but in other cases you can't unify your state, or you're dealing with an external stateful system (like the DOM), and you have no choice but to find a way to keep separate pieces of state in sync.
I should probably write a blog post on this
- rwmj 6y agoThe way Tcl/Tk dealt with this was nice: You could watch the value in a variable, getting notified when the variable changed. GUI controls could therefore exactly reflect the content of variables. Of course this comes with a certain hidden overhead. This complete example will toggle the checkbox every second (1000ms), or the user can click to update the variable. The checkbox watches variable "v". #!/usr/bin/wish checkbutton .button -variable v -text "Click me" pack .button proc run {} { global v after 1000 run set v [expr !$v] } run
- brundolf 6y agoMobX is the equivalent for the space of reactive web frameworks, and I agree it's a fantastic model. The cost is that it requires a little "magic", but the benefit is that the entire question of synchronizing state virtually disappears, leaving you to focus on modeling and controlling state (which are still nontrivial)
- trulyme 6y agoNo. Just no. You simply can't use "MobX" and "fantastic" in the same sentence. There are just so many problems with MobX. For example reactions - ever tried figuring out why some value changes in a bigger app? Not to mention abysmal tooling (compared to Redux DevTools). But the biggest problem is that everything is... sprinkled with magic. Just give me Redux(-toolkit), thank you very much, I can understand these much more deeply. /rant If I sound confrontational, sorry about that... I just had the misfortune of inheriting a MobX app. Magic indeed.
- Sophistifunk 6y agoI've had the exact same experience, only the problem was redux and the solution was mobx. Anecdotes are not universal truth.
- DecoPerson 6y agoMy experience with MobX has been the opposite. I introduced MobX (along with HTML5 UI, React, TypeScript, etc) to a large team and it went swimmingly. Debugging/stepping-through was no more tedious than regular Chrome DevTools debugging. I recommend using MobX’s strictest setting (where changing reactive objects can only occur in named actions), and restricting reactivity to a monolithic “model” (mdl) object and its children. It really does make writing fast, correct & good UI a breeze, in my experience.
- brundolf 6y agoThe thing about MobX's magic is that it is small, and simple, and easy to learn predictably. Once you understand it, it's only "magic" in the sense that it's automatic, not in the sense that it's inscrutable or unpredictable.
- Jasper_ 6y agoThis was the "two-way data binding" model that Angular used and React famously knocked down. It's been part of UI toolkits for a long time. Remember Object.observe?
- tenaciousDaniel 6y agoYou could conceive of a GUI as merely a projection of internal state. If you do, then a GUI could be a completely stateless layer that exists solely to render visual content parametrically. I've been developing a convention in React over the last year that uses this idea and it's very very nice. I'm also trying to write a platform-agnostic UI language specifically for designers that makes this a first class concept.
- riquito 6y agoUnless you rewrite the content of every input and textarea and reposition the cursor at every input event, or monitor which element has focus at any given time, you have some DOM components with an internal state.
- erikpukinskis 6y agoWhich... you mostly can do that with React. Focus is the hardest one, because that can move around really erratically. But even that sometimes has to be done in state. IE11 doesn’t have descendant focus selectors so at my last job I wrote a hook for our dropdown children to dump their focus state into a React context so our renderers could stay pure and not rely on CSS and therefore DOM state. Just last week I implemented a hook to reposition a tooltip based on the mouse cursor. You do need to think about DOM state a little when doing these things. But I would argue that’s somewhat separate from the activity of building a React UI. It’s pretty rare you can’t just render purely based on the React state, using off-the-shelf hooks.
- theknocker 6y agoPeople do this sometimes. It can work out pretty well.
- legulere 6y agoWhat you describe is the model and view part of the MVC pattern: The view is just a projection of the model. How does the UI get notified of changes? (like the article discusses some changes might come from different part of the UI, or might even come from external like in a chat client) How do you handle actions of the user? (Of course in the controller in MVC, but how does it work exactly?)
- dustingetz 6y agoI/O, not state (well they are the same thing mostly). Async, latency, concurrency, failure, effects
- marcus_holmes 6y agoI was wondering why this was all so much easier back in VB than it is in the browser, and I think you're right: we've got to keep the state in the DOM and the "useful" state in the program in sync. Whereas in VB there was only one program so only one source of truth (though it was possible to get your GUI desynced from your database, you kinda had to work hard to do that). I think this is what Elm solved (and then by plagiarising the same approach, React and Vue). Make the interface declarative rather than imperative and voila - state is automatically in sync.
- jayd16 6y agoAgreed. To some degree UI programming faces many of the same problems you see when building a distributed system.
- miguelrochefort 6y agoIt's not a coincidence. It's the exact same problem.
- AussieWog93 6y agoFunny you mention this. I used to think the same way, and would constantly trip up managing state, until a co-worker who had worked in video games for two decades introduced me to the concept of the Immediate Mode GUI (IMGUI). Casey Muratori first spoke about IMGUI back in 2005, but didn't actually implement it practically: https://www.youtube.com/watch?v=Z1qyvQsjK5Y https://www.youtube.com/watch?v=Z1qyvQsjK5Y In around 2013, Omar Cornut wrote an incredibly high quality practical implementation of Muratori's concept called _Dear ImGui_: https://github.com/ocornut/imgui https://github.com/ocornut/imgui Using both Cornut's library and Muratori's mindset is incredibly powerful and liberating. Things that would require days of work and multiple files in Qt or Cocoa can be finished in four hours and a couple of hundred lines of IMGUI code. It also uses an order of magnitude less CPU/memory resources (which was an issue for us as we were rendering and displaying RAW video footage in real-time). I find it amazing that this way of thinking hasn't completely dominated frontend programming by now. There is literally no downside to using the IMGUI concept - entire classes of bugs disappear, and your code is simultaneously smaller, easier to maintain and more logical in flow. It's also a shitload more fun to write (something I think that SWE culture overlooks too much) - you spend the majority of your time writing code that directly renders graphics to the screen, rather than fixing obscure bugs and dealing with the specifics of subclassing syntax.
- kuraja 6y ago> There is literally no downside to using the IMGUI concept There's a big downside, the performance penalty. For a GUI that renders moderately complex objects, the cost of not caching becomes overwhelming, the equivalent of losing 20 years in GL architecture advances. Pushing the VBO to the GPU each frame is the same as losing indexing. My own application doesn't render at 60 fps in immediate mode. I find that people who believe that IMGUI is somehow faster than RMGUI are game developers who have been taken in by marketing, because basic knowledge of GPU programming (i.e. what is indexed rendering) is enough to see that this couldn't possibly be true. Their UIs are usually simple enough that the performance penalty is not important. And many RMGUIs have heavy styling, visually incomparable to their IMGUI counterparts, which makes the average RMGUI far heavier.
- 6y ago