the first opinion i have should come as no surprise: i hate using electron apps, or browser based applications. the big reason? they never work offline, they rarely work on an intermittent or slow connection, and god help you if you're on a metered internet connection.
it's easy to label the problem as "the app is too much like a web browser", but in some ways, they aren't browser-like enough. they don't cache anything. you can't just type in a url. you can't even override the css, or turn some feature off with adblock. sometimes it feels like using a regular browser + webapp is an improvement.
even so, a real browser wouldn't change much. the underlying application is still a thin client to some service elsewhere. instead of offering a protocol, allowing users to customise or control their experience, people build thin applications that don't work offline. i can't really blame them for it, building an app to work offline is not just a matter of slapping in "from replication import sync"
in other words: I don't hate electron apps, I just hate what they're used to build, and i wish people would stop doing it.
which brings me to my second opinion: browser based applications are by far and wide the easiest way write cross platform software, online or offline, and i wish people did more of it.
if you're as old as me, or worse, a tiny baby who loves "retrocomputing", you will have suffered under traditional ui toolkits, and i might not need to explain much of why web apps are nicer, but for the sake of posting: let's get to it
early GUI protocols like X11 worked by sending drawing commands for each pixel to a display server, handle events from the display, and also work out how to redraw things to the screen when things got updated. it was not fun.
sooner or later, we accepted widgets were a thing. an object that declares what's drawn on screen, and a series of child widgets to fill in the details. although we still had to write untold callbacks to make things work, we did make things work.
again, it wasn't fun. resizing a dialog box on windows involved manually recalculating every widget position. mac os wasn't much better, but did have a notion of resources: using a tool to design the forms and widgets on screen, saving it to a file, and loading in this declarative description of the interface with code, rather than rebuilding it from scratch each time
eventually, qt entered the ring. qt also has a notion of writing declarative interfaces, qml, but it's qt's signal, slots, and properties that really made a difference to making things less painful.
in a callback based event system, it's very easy to end up duplicating code across event handlers, and it isn't so easy to keep the widget and application state in sync. qt argued for a somewhat radical change.
your widgets can receive events (mouse moved), or create events (close and save), and these are called signals in qt, and every widget lists the signals that it can emit. these are connected to slots, the qt term for callbacks. finally, properties make the big difference. they're state on a widget that can be connected to signals, slots, as well as other properties, which means they will recalculate their value when their inputs change, much like a spreadsheet
with qt, instead of writing a callback that manually changes eight widget values and some application state, you break things up into distinct events, and distinct properties which depend on each other. signals and slots clear up a lot of the duplication, and properties allow you to keep all the states in sync with each other. it's still not fun, but it is a whole less painful.
you can take qt's properties one step further: functional reactive programming, or dataflow computation, which are just fancy pants ways to say "it works like a spreadsheet". you change one value, everything gets efficiently recomputed, on demand.
that's what adobe's adam & eve did, literally a spreadsheet with a js-like, declarative expression language, and qml a declarative gui language atop. the problem this solved at adobe? widgets were hard to compose, near impossible to reuse, and a huge source of bugs came from manually wiring up all the dataflow calculations.
the reason i bring this all up? with a html dom and a bit of javascript frameworks, you can solve these problems in very similar ways. it's one of the reasons why writing browser/electron apps is so appealing, using something react like to build up the ui.
there's a widget set (components) and a declarative language (inline xml) for specifying them. there's widget properties which can be chained up together to be recalculated automatically.
there's also a few things react does that qt et al don't do.
in a qt app (and many others), the idea is that you create a widget tree in memory, and update the tree's properties as the application state changes. in react? you build a whole new dom tree when you change the state, and the react libraries then apply the new bits of the tree to the existing copy in memory.
it's a very similar notion to immediate rendering: a games programming technique where a UI is re-rendered every frame from internal state, rather than using some widget tree in memory, trying to efficiently work out how to only change one part of the screen, or work out which dom elements have been mutated since the last update.
the advantage of this approach is that you never worry about keeping your widget dom in sync with your application, and you'll never get into weird application or ui states from forgetting to wire things up in the right way, usually
it's also a lot nicer to write something that just produces a dom output, like a template, than it is to work out how to mutate that dom every time something changes. it's one of the nicest parts of using react.
the other nice thing worth mentioning here? react has some notion of "addresses", or "routes", or even "pages". it's a whole lot easier than having callbacks to close the open window and redisplay the next thing in the application. you might have to suffer a bit more through desktop ui toolkits if you don't believe me immediately.
that said, webapps aren't the only frameworks with notions of hyperlink-like navigation between pages. android has intents, and i'm sure there's others, but i'm already going way beyond my point
no matter the toolkit, you will end up with some declarative form of your user interface, some shared state with dataflow propagation, and some message or event system to glue the parts together. in one way or another, the distinction between how web apps and how native apps are written is no longer so clear.
which brings me back to my point, if you're still with me: why not pick the toolkit that's cross platform, most of your developers already know?
as much as I like qt, and would highly recommend it, i have to admit that electron like apps are an incredibly effective way at building cross platform applications. it's relatively easy to target web and desktop and mobile at the same time, and if you use a modern framework, you can escape the callback hell. it's a bit nicer to write, too.
which is why i think we should build more of them. sort-of.
qt is already a bit of a browser, parsing and rendering QML into a DOM made of QObjects linked up with signals, slots, and properties, sure enough, but i think it'd be a lot nicer with pages, navigation, and hyperlinks too. it should be more browser like. i'm still not entirely sure about dom-diffing and other ideasa, but there's lots of plenty of good ideas to borrow.
i really do think we're seeing a general convergence on how to write ui software:
- page like navigation, with some notion of a back button
- a declarative form of specifying a widget tree (or component dom)
- functional-reactive/dataflow computation of widget state
- immediate rendering, rather than in-place update of dom
and it really wouldn't surprise me if someone gets nerdsniped and ends up writing an Entity-Component-System once they tire of inheritance for widget properties. and maybe, just maybe, we might even start writing desktop software that works when the internet is down again.
which brings me back to my first objection. although a browser-like design makes ui toolkits a lot easier to use correctly, we only seem to be using it to write thin clients for websites.
it makes me nostalgic for rss, smtp, and xmpp. not because the software was any good, but at least you could pick and change things about the way it operated. nstead we just seem to be shipping one browser per website, and creating a weird imap-monster out of http and json.
hooray!
