HACKER Q&A
📣 tripleo1

Why is GUI programming so hard?


Some smart guy (may or may not be Rich Hickey) was allegedly heard to have said about GUI programming, "I don't do that kind of stuff."

Over the years, I have observed the fact that some /many things about GUI is/are just unnecessarily stupid.

See Jgoodies-binding, and more recently elm-lang and htmx for unexamples of this.

btw, rip


  👤 mikewarot Accepted Answer ✓
Visual Basic 6, and Delphi 5 made GUI programming trivial. You drag/drop GUI elements in place, then hook up event handlers.

These days, there's a lot more boilerplate in most languages. C# was a horrible downgrade.

If you can put up with the documentation, Lazarus/Free Pascal works amazingly well, and is almost as easy as it used to be.


👤 proc0
It's deceptively complex. What looks like buttons and sliders ends up having a lot of interactivity that is underestimated. Then there is the complexity of both the software and hardware stack, from different displays and devices to a rapidly evolving ecosystem of libraries, frameworks, and such. Add to this the complexity of the networking stack (at least for web apps) and it's not hard to see why even UIs with modest functionality become very large and complex.

There is also something to be said about how organization structure their teams to build UIs and APIs, which is to scale productivity by adding and leveraging more people, as oppose to leveraging more powerful code. This is probably more true on the frontend as it is typically not as critical to the business as the backend, so it is not surprising to see UIs constantly break or lack any proper standardization.


👤 spit2wind
GUIs are one giant state machine. Tracking all those states is unwieldy. The best notation I've seen is state charts, as described by Ian Horrock in Constructing the User Interface with Statecharts. Still, it's a ton of work. As a result, everyone I've ever seen just resorts to the 80% solution of coding it up without tracking the states and then playing whack-a-mole trying to make it consistent.

👤 eternityforest
Armchair psychology warning!

Try doing something in Vue, Flutter, or SvelteKit or something... it will probably be significantly easier than what you expect!

The hardness comes from the fact that you're basically writing bookkeeping two way state sync code, and if you don't have a reactive framework you're doing it by hand.

Plus, there are so many GUI libraries, and the easy ones are big. I suspect GUI haters choose low level stuff, then complain about how hard it is.

Or, they might use language without that great of GUI bindings. They might also start out with a specific vision of how it should work, whereas people who find GUIs easy are picking a big popular framework and not really thinking of any ideas outside it's language.

I generally don't even start thinking about architecture or code until after I've already chosen my tools, I want to do designs that fit the tools I'm using, not design something and than choose a language specifically for the design.

Plus, you cannot build a nice GUI on top of a UNIXY backend without lots of work. For some reason I don't understand, programmers seem to think of computers as devices that take input and produce an output, and build stuff that looks like a compiler tool chain.

With GUI, you're not computing an output, you're updating a state based on user input. You generally never want to be in a place where you do things in a sequence, and can't edit previous steps without starting all over.

You also can't always have a logical model for what to include.

Usually GUIs are not general purpose like raw code is. You're not using a blank canvas to build another blank canvas, which is what most devs seem to like, you're building a curated workflow.

You might have "Edit this transaction" buttons and "Export report for the month" buttons. If you're used to thinking in logical layers that build on each other, you might not enjoy essentially recreating some illogical business process in code.

It seems like programmers are really code-philosophers and code is like a meditation for a lot of them, and they seem to get depressed and discouraged working on things that don't have any beauty or logic or reason and are just reflections of some messy illogical real world process full of extra stuff to deal with untrained users.


👤 cookiengineer
The biggest issue with GUI programming is always "when to reflow" and "when to relayout".

Take fading in sidebars, for example, which influence how the main content frame is rendered and are different in size on mobiles (e.g. icons, icons with labels, bigger icons, bigger labels or even a more nested structure on desktop, with a burger icon for fade-in and fade-out).

This is almost impossible to implement if you only have horizontal and vertical box layouting at your disposal, which is the most common denominator among frameworks and their renderer concepts (GTK, Springs, QT, etc).

Flexbox and tweenable properties like transparency, rounded corners, margins, paddings, colors and z-indexes are almost a hard requirement these days in terms of UI design. And those features are very hard to implement without a renderer pipeline that can influence both fragment and vertex shaders.

And this is not talking about state management of the UI elements, which is a whole world of problems on its own. React Native's approach, for example, is utterly broken on older mobiles due to how they re-flush the whole state tree on every single frame (which makes old mobiles lag due to them not being able to keep up with the amount of FPS required).

Getting the reflow right with e.g. calendar widgets and calendar popup views which are rendered by native APIs is a nightmare. As there is no unified way to do it across platforms, there eventually will be a lot of redundancies that are implemented, and a whole lot of quirky code behavior.


👤 PaulHoule
I don’t know if it is that GUIs hate tests or that tests hate UIs but either way it means UI code is hard to test.

The trouble is that a UI element usually calls the framework and gets called by the framework so you wind up needing mocks and such. Or you have something like React which is just batshit crazy (e.g. do I wait until the component renders 7321 times or 7322 times before I can check that it is in the state it is supposed to be in?)


👤 vfclists
GUI programming is hard because some industrialists realized that if they switched the whole world to web based applications they would be able to hoover up information for free and got everyman and his dog to jump onto the everything must be a web application bandwagon.

As for web development frameworks, GUI and otherwise, they are like nuclear fusion, only in this case a new framework is announced every two weeks that is claimed will solve every development problem.


👤 1attice
[context: frontend eng here, with a CS background and lots of experience on the backend]

The reason frontend dev sucks so much, essentially, is humans.

Have you met humans? They are opinionated, dogmatic, and hidebound; their habits and preferences are arbitrary, and, collectively, comprise their horison the way the bars of a cage do a bird's.

A slight user preference for something inconsequential, like, say, a realtime indication of password strength, or an absence of loading delays, means that if your product does not "meet user expectations" for some some incredibly inane value of `$EXPECTATION`, you can reliably expect your competitors to consume not just some, but eventually, all of your sales, and is therefore strongly selected against.

Recalling that you are yourself substrated upon a human, you know exactly what I'm talking about. Be honest. Are all of your preferences rational? What even is 'rational', anyway? I'm not just doing a lazy gesture to pseudo-philosophy here, I'm actively asking you to define practical rationality (not just logic, mind you) in a way that has no reference to common practice, intuition, or habit. Good luck :) (Note: I wasted my twenties in a philosophy PhD programme, so I know enough to advise you that this is a honeytrap that you can literally spend decades unsuccessfully trying to answer. I know I did.)

Anyway, because of user expectations -- expectations like: bespoke widget sets, branding, performance, speed, similarity with native app, cross-browser compat, etc. -- we -- us engineers -- built elaborate tooling back in the day to accomplish all this, for 2008-ish values of 'back in the day'. Some of these, like jQuery, eventually crystallized into new browser APIs, but a lot of them involved various kinds of either stack lock-in, or conceptual lock-in. (React does both.)

Remember how I said humans were creatures of habit? Well, horribly enough, engineers are humans too, and we can't get good (really good) at things until we've put in 10k hours or so. So, if you've put in 10k hours into React, you're going to be at a competitive disadvantage if you move everyone to a saner alternative, such as htmx. This, too, is strongly selected against.

So, there you have it. Frontend development is terrible because it's the part that touches the most humans.


👤 dwaite
The core of a GUI framework is nearly always written as asynchronous events and drawn responses, with the developer at that level responsible for the state machine in the middle and invalidation of the GUI in response.

Coordinating large asynchronous systems by hand is challenging. There can be surprising interactions. For example, tapping a button again in the middle of an animation is an example of something where the complexity often leads to the program getting in a bad state or even crashing.

This is one reason that structured concurrency and asynchronicity primitives have been added to many programming languages - to make reasoning about and managing such state machines easier.

Some modern GUI frameworks attempt to simplify this by instead let you declare the UI and its relationship with your data, the interdependencies there, and may have sophisticated means to monitor data changes. This breaks you from having to maintain most GUI state within your program - you respond to user actions by updating your program state, and the GUI responds to those updates.


👤 vismwasm
I always try getting into frontend frameworks but it's just overwhelming. For WebDev there are a trillion frameworks which you need to append with another framework as the each framework doesn't really solve the problem by itself.

I looked into Flutter & Dart as it seems thatr everybody loves it. But then apparently even for Flutter you need another framework for state management. I thought state management is the core issues these frameworks want to solve?

I would've thought game engines have solved the problem of complex state management though. There are games with reactive in-game browsers/websites which work better than most real websites!

So far the easiest for me to grasp and getting started was actually react / nextjs:

- Extremely well documented

- Little boilerplate (especially compared to Flutter - I find that StatefulWidget really ugly)

- Combined with a component library it's incredible easy to get started


👤 smoldesu
I would argue it's a "give a mouse a cookie" situation. On the simplest side of things, stuff like Zenity exists for super-simple GUI dialogues and user input but isn't very customizable. You want a window model with a visually-distinct root window and identifiable dialogues and child processes. You also want async management between those windows, atomic data handling for both processes, signal handling for sending data between them, GPU-accelerated animations... what we really end up wanting is pretty much an entire OS.

The best GUI toolkits I've used are either heavily abstracted (tkinter/pygame) or absurdly full-featured (GTK/Qt).


👤 jbverschoor
Because every six months we start over again with new models, libraries, tools, compilers, transformers, names.

Except stable APIs and documentation.


👤 tripleo1
I started thinking about this the other day because of this question at we-turned-everything-into-a-google-trap-and-now-it-has-ai-too-dot-com, with-a-subscription-business-model (https://www.quora.com/As-someone-who-does-some-programming-f...)

One of the answers does mention FLTK, which I should have included above.


👤 gardenhedge
The hard part about GUI programming is that it involves managing state. Managing state is hard.

👤 bsaul
i think the nature of GUI programming hasn't been well enough characterized, and thus the tools we use for building them aren't adequate. it's a bit like trying to do DB programming before transaction, and relational algebra were invented.

Gui has a lot of conceptually complex properties :

- it has both synchronous and asynchronous behaviors ( drag vs trigger an animation or loading data for the next screen )

- it has i/o (the screen)

- it is interactive (a user can click at any point in time, interrupting the process)

- it has transactional properties (you sometimes want a whole set of changes to be performed atomically, with nothing interrupting it).

-it is working both in diff mode ( change just the color of that button) and in whole state change (load a new screen)

all of this make the problem quite challenging.


👤 viraptor
I'm sure there are many issues with GUIs. My main one is that lots of things can't be (easily) expressed in the API of common languages. For example you set the colour of something to red? Well, that thing renders in some specific way that calls a callback which in some cases will override the background, so setting the background colour will not do anything. You can't express that in objects, there's really no failure here beyond "you didn't consider every possible layer and combination of features". Yet, whenever I try to create some GUI, I run into an issue like that every few minutes.

👤 naruhodo
What exactly is "hard" about it?

Decades ago, I used zApp, wxWidgets, Java Swing, Qt and Python GTK bindings. None of those were particularly hard.

What blows my mind is how long it took the web to get flexbox (Java GridBagLayout, IIRC).


👤 quickthrower2
Why are elm/htmx considered stupid?

And UI programming is hard because of the user you are interfacing with :-) and the fact you are not forcing them to have amazing working memory needed to deal with a CLI.


👤 o11c
It's a combination of 3 things:

* Parts are fundamentally declarative and parts are fundamentally imperative. This applies both to the abstract problem, and the approach taken in particular toolkits, and the border is not in the same place.

* The state involved is stored in at least 2 places which are distant from each other, and that opens all sorts of logic and timing problems.

* The same GUI framework gets used both for "wait for an event" UIs and "update every frame" UIs.

Abstraction is hard.


👤 renewiltord
It’s because you need to bubble state through to all components. Implement a spreadsheet to get a grasp of the initial problem. Then consider that you need to partially update for performance.

I rarely program GUIs but when I do I use React and it works quite well quite easily.


👤 weare138
Devs were so preoccupied with whether they could, they didn't stop to think if they should. Our industry seems to have a problem with FOMO and leaving well enough alone. Most modern web GUI frameworks and modern software in general are engineered around buzzwords not usability. We can't seem to just stick with simple boring things that work and constantly reinvent the wheel because we didn't like the hubcaps.

👤 sorokod
There is a big social component: everyone has an opinion, everyone is an expert.

People who are indifferent and uninterested in non UI logic, will speak with confidence and criticize UI.


👤 DeepSeaTortoise
IMO GUI programming isn't difficult by default, e.g. have a look at LabVIEW.

It's just that all of the tooling is beyond exceptionally bad.


👤 joeld42
Because UI, like build systems, are really just huge state dependency graphs in disguise.

👤 aristofun
You don’t usually have such a complex state on the backend. That’s why.

👤 firemelt
its not hard just full off hassle

👤 ganzuul
Interface is hard. Users are hard. Graphical is hard. Then you add three-way integration on top.

There is just so much potential close at hand but out of reach. E.g. Steam Controller.