Great article, but I’m not really sure the current react-alike path we (industry-wide) appear to be on is the correct one. It seems to be we’re going through a lot of trouble to pretend things aren’t the way they are, rather than just embracing it and developing disciplines around managing it.
I think it’s right to be skeptical. React and its variants are solving real problems for certain classes of UI problems, but to date nobody really knows what a DAW or CAD program written with reactive patterns would look like or how well that would work out.
My personal approach to this is to offer good “escape hatches” for dropping to a lower level when the reactive layer isn’t the best fit. In current Druid, this is the “Command” mechanism, which is clunky but lets you apply imperative UI patterns pretty easily. In the Crochet prototype, I offer the low level tree mutation API, which is probably no worse than imperative DOM mutation, though almost certainly faster. And it might be possible to layer interesting things on top of that.
I don’t think reactive is necessarily the wrong way to go about building GUIs, but I think it requires a stronger “framework” (probably not the best term) than an embedded DSL, be it in Swift, JSX, or Rust. Not only that, I believe that certain things (one example being modals) should never be shoehorned into the twin-trees paradigm we see in react where the call graph / container hierarchy and screen-space-subdivision tend to be the same set of of entities.
I don’t think it necessarily requires a separate implementation language, but it should be more than you expect to always have available in a general-purpose language as we see them today. It should have declarative options to describe structures and hierarchies, and the concept of context (be it via component hierarchy or call hierarchy) should be built-in, alongside the assumption of cyclic invalidation/validation cycle. Add a well-thought-out (and typed) event system including observables. Think of a mix between Flex’s MXML and [Bindable] system, and React’s declarative functionalish strategy (within a single component), but implemented mostly at build-time like Svelte.
When you build around an established component lifecycle with language support for (in)validation of computed state (and rendered output), I believe a lot of the things people have been told to hate about “OOP” will once again become benefits, rather than risks and complications.
“Developing disciplines around managing it” has severe limitations. I find systems thinking an illuminating lens here: it’s far more productive to make both cars and roads safer than to lean on the idea of trying to “develop disciplines” around better drivers. There is only so much you can do on the latter front. There’s a lot you can do on the former front. I’m increasingly of the view that the same goes for language design, framework design, etc.
We did try the path of “embracing” the way things are in web UI programming (and other kinds of UI programming, too). At least on the web, where I have fairly deep experience with it… it was terrible. My experience trying to pick up UIKit didn’t make me think that was going to be a better experience than writing raw imperative DOM, either. Approaches like React are much more tractable in practice. (That includes my favorites on the web, Elm and Glimmer—n.b. that latter links to a post I wrote doing a deep dive on how it works.)
To be clear, I use React all the time, have done for years now. If I were to green-field some web stuff right now I’d use Svelte, now it’s grown some TypeScript. Compared to DOM, React is ambrosia from heaven (or at least it was, until they started trying to turn JS into OCaml, but I digress). But it’s not so great when compared to Adobe Flex, for example.
I have to read this it breaks the tag record!
He also talks about Haskell and lenses, so I could have upped it further!
Next time :) It is almost 5k words, very dense, and with tons of links to other resources, so does cover quite a bit of ground.
Great article, but I’m not really sure the current react-alike path we (industry-wide) appear to be on is the correct one. It seems to be we’re going through a lot of trouble to pretend things aren’t the way they are, rather than just embracing it and developing disciplines around managing it.
I think it’s right to be skeptical. React and its variants are solving real problems for certain classes of UI problems, but to date nobody really knows what a DAW or CAD program written with reactive patterns would look like or how well that would work out.
My personal approach to this is to offer good “escape hatches” for dropping to a lower level when the reactive layer isn’t the best fit. In current Druid, this is the “Command” mechanism, which is clunky but lets you apply imperative UI patterns pretty easily. In the Crochet prototype, I offer the low level tree mutation API, which is probably no worse than imperative DOM mutation, though almost certainly faster. And it might be possible to layer interesting things on top of that.
I don’t think reactive is necessarily the wrong way to go about building GUIs, but I think it requires a stronger “framework” (probably not the best term) than an embedded DSL, be it in Swift, JSX, or Rust. Not only that, I believe that certain things (one example being modals) should never be shoehorned into the twin-trees paradigm we see in react where the call graph / container hierarchy and screen-space-subdivision tend to be the same set of of entities.
I don’t think it necessarily requires a separate implementation language, but it should be more than you expect to always have available in a general-purpose language as we see them today. It should have declarative options to describe structures and hierarchies, and the concept of context (be it via component hierarchy or call hierarchy) should be built-in, alongside the assumption of cyclic invalidation/validation cycle. Add a well-thought-out (and typed) event system including observables. Think of a mix between Flex’s MXML and
[Bindable]
system, and React’s declarative functionalish strategy (within a single component), but implemented mostly at build-time like Svelte.When you build around an established component lifecycle with language support for (in)validation of computed state (and rendered output), I believe a lot of the things people have been told to hate about “OOP” will once again become benefits, rather than risks and complications.
Two thoughts here:
“Developing disciplines around managing it” has severe limitations. I find systems thinking an illuminating lens here: it’s far more productive to make both cars and roads safer than to lean on the idea of trying to “develop disciplines” around better drivers. There is only so much you can do on the latter front. There’s a lot you can do on the former front. I’m increasingly of the view that the same goes for language design, framework design, etc.
We did try the path of “embracing” the way things are in web UI programming (and other kinds of UI programming, too). At least on the web, where I have fairly deep experience with it… it was terrible. My experience trying to pick up UIKit didn’t make me think that was going to be a better experience than writing raw imperative DOM, either. Approaches like React are much more tractable in practice. (That includes my favorites on the web, Elm and Glimmer—n.b. that latter links to a post I wrote doing a deep dive on how it works.)
To be clear, I use React all the time, have done for years now. If I were to green-field some web stuff right now I’d use Svelte, now it’s grown some TypeScript. Compared to DOM, React is ambrosia from heaven (or at least it was, until they started trying to turn JS into OCaml, but I digress). But it’s not so great when compared to Adobe Flex, for example.