Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

After reading the "Grug Developer" article recently, I've been thinking of frontend development as "The Plane of Eternal Complexity Demons".


This is because UI programming is inherently extremely complex, especially compared to something like a stateless API tier running in AWS. It’s stateful software deployed to countless different runtimes on hardware you don’t control. Instead of a smattering of API routes handling well-structured semantic datatypes like `POST /burgers?pickles=false`, input comes in the form of arbitrary UI events from various input devices like pens, keyboards, mice, etc that must be interpreted to have a semantic meaning. Often there are hundreds of API routes (event handling elements) on screen at once in a complex application. UI engineers are perpetually frustrated by this complexity, and so some small percentage look for better ways to handle these issues.

Of course it’s best to avoid UI programming entirely, but in many domains it’s necessary.


There are definitely examples of UI programming that is more complex than certain APIs that largely perform basic CRUD operations, but I'd strongly disagree either is inherently more complex than the other, it's just that human behaviours and preferences are messy and unpredictable, which means conceptually "simple and elegant" UIs are often not what users actually enjoy using, and this inevitably has impacts at the code level. APIs don't have to designed to deal with human eccentricities as they're written for developers, and we aren't like normal people.


I find the big difference for me when building an API vs working on a UI is the testing. I think backend APIs tend to be much easier to test than UIs. For the backend, it's mostly Request in Response out, check they look good and the side effects (database, caches, queues, etc.) are performed etc. For the UI you have a lot of async stuff going on and writing non-flakey tests is tricky and verbose with the current tooling - using react testing library which is better than enzyme, but still harder than testing a Django endpoint.


Absolutely - realistically you never can automate UI tests fully, as there's no way of describing all the things humans "expect" to experience while using a UI. Even when you can, the effort involved in creating and maintaining the tests and confirming that the failures are genuine often doesn't justify the benefits.


I think this suggests that UI is more complex than API.


Then you've never written APIs that have to do super complex calculations or process huge amounts of data efficiently and reliably. By far the most complex code I've had to deal with has been "back-end engine" type code, even if it was technically part of a desktop application (but wasn't dealing with user interactions).


My point isn't that "all UI is more complex than all API", but that the constraints and nature of UI tend towards complexity (especially incidental complexity) at a higher rate than API programming. As you observed in a previous post, UI engineers struggle to use techniques like end-to-end testing that API engineers use with relative ease. Why is that? My argument is that engineers working in the API space more completely control their problem space in general. Some examples:

- Want to rigorously specify the interface of an application? In API space, we can use an IDL like Protobuf to write a contract of exact input and output types. In UI space, the best we have is plain-english text language called Gherkin.

- Want to record all inputs and outputs made to application to verify them against new version? With network APIs, we can often record all app-level IO in production using network capture; often with negligible performance impact. To do best possible job for deterministic replay, we can actually hook into our CPU if we try hard. UI? Sorry, again we're running on a customer device, unlikely we can apply these technique. At best we may be able to capture some UI change traces on a few devices with spare bandwidth and CPU.

- Having performance troubles? In API space, feel free to buy more hardware, or optimize more tightly to the existing homogenous platform. Oh, maybe application takes a few minutes to boot up and "warm up"; this is fine, we'll use blue-green deploy and replay a bit of the read-only traffic we captured earlier... In UI space? We probably need to consider 2-3 versions of ~5 different operating systems, running on myriad heterogenous hardware, to say nothing of browser issues; where every few weeks Google releases a new runtime with the potential of performance regressions. Slow to boot? Say goodbye to users; we need the app to paint in 1.7 seconds and be interactive in 3.8 seconds, on demand at any time of day.

- Have a problem with teams stepping on each others toes? In API space, you can try to deploy two services (not saying this is good idea, but plenty of people see it as solution to this problem); end users won't know the difference. Try to deploy two separate apps in UI land? End users will be sad.

- Need to handle large amount of data in API? We have low latency access to storage APIs that scale to petabytes. In a UI? We'll need to build an API first to mediate streaming access to that data and store it for us, since we can probably only store a few hundred megabytes locally before we run out of disk. In both API & UI we need to add a local cache, but how do we test local cache provides good experience? This takes us back to testing topic... where API seems to be easier.

An argument from anecdotal experience isn't worth much in this territory; I can easily same the same thing in reverse: the most complex code I've had to deal with is threading the very narrow constraints of contentEditable programming for Notion's rich text editor. Now let's add a dash of "no true scotsman" as well: You must have never written any such complex UI! See? I think this is an unsatisfying approach to the issue (and not one I make in earnest).


I don't disagree with anything you've written there, but I still disagree that UI code is typically or inherently more complex (or harder to write well) than backend code. I doubt it's anything you can even prove one way or another. But while the nature of inputs and outputs for UI code tends to be nebulous and somewhat poorly defined, it's hard to argue the range of possible inputs compares with code that has to process massive datasets.


Bullshit. In 1995 people were creating desktop UIs order of magnitude more complex than today's anemic webapps, without any of the braindamage-inducing stuff that's happening in web UI development.


I was legitimately curious about this--my memory of Windows 95 is not this nice--so I looked at Wikipedia's list of software released in 1995:

https://en.m.wikipedia.org/wiki/Category:1995_software

What software specifically do you recall being "an order of magnitude more complex" than today's popular web apps?


Win 95 was a toy, NT was getting there. Apps were being ported quickly to NT4.

I do remember using Maya on Irix in '97 or so and it was already pretty amazing. It was built off earlier applications like power animimator, which was started in '88:

https://en.wikipedia.org/wiki/PowerAnimator

Maya had a customizable interface, and neat things like pie-menus, although not invented there.


Just from the top of my mind: Excel, Word, Photoshop, Windows Commander (called Total Commander today), SolidWorks, AutoCAD, Borland Delphi.


Excel is quite complex, but the Excel of 2022 is far more complex than the Excel of 1995, and part of it exists on the web itself, so Excel '22 would be an invalidation of your argument that '95 apps were more complex (as well as other modern versions of the other apps).

One major difference in 1995 applications is that almost none of them were collaborative or synced with a remote server. They were all isolated applications that worked entirely in a local context. They could be programmed to a single target platform on perhaps one to three screen resolutions (640x480, 800x600 and 1024x768). They could all work under the assumption that one style of input was being used (mouse and/or keyboard). They all could use simple built-in dropdown context menus. They could all render to a canvas context graphics with much of the heavy lifting assumed by the operating system itself.


We certainly had network programming in the 90s. It was just that apps didn't use it unless needed. SGI res was typically 1280x1024 and Wacom tablets were common in studio/professional settings.


Apps didn't use it because it wasn't practical or in high demand yet. People were just getting used to checking email and most people were only intermittently online via dial up. Collaborative apps would take another 8 or 9 years to really start to take off.


We had T-1 internet to every desk in ‘94 and I used dozens of networking apps from archie to veronica. Probably used CU SeeMe before a browser. Though Mosaic dropped around that time.

Advanced collaboration still in the future, this era was more like chat and file transfer. I think you could mark up Word docs from a network drive at some point.


We went to the moon some +50 years ago. We ought to have solved "UI programming" already, no?

Something is not working


UI programming is much harder than going to the moon. Do not confuse danger, scale, glamour, etc with difficulty


Ultimately, successful products are determined by customers and by product managers and their executives, and it turns out there is no one-size-fits-all approach to even basic UI programming because everyone has an opinion.

Not to mention, as an example touch became a widespread new UI paradigm in the last 10-20 years.


simple problems easily becomes complex in mainstream contexts.. due to bazaar like soil. NASA had to solve one immensely hard problem but they owned the context. Vertical integration if you will.


By that logo , SpaceX shouldn't exist.


I disagree, I think UI programming is inherently quite simple. Especially with a paradigm like immediate-mode GUIs in my opinion. I believe the complexity comes from the fact that the DOM is a poor API for creating user interfaces, which ultimately inspired developers to create frameworks that work in a more “immediate-mode” style way.


The native UI toolkits are even harder to use than something like React and recently have been evolving to a similar reactive + declarative paradigm.

User interfaces are complex, poorly specified, and subject to rapid and often capricious changes in the middle of development. Don't blame the tools.


JavaScipt on the browser is cursed[1].

1. There is no standard GUI library, as per article. A GUI can be as arbitrarily complex as you wish, and every different frontend system is a unique GUI system deployed in JavaScript, usually using HTML for the view drawing primitives* and events for input. The complexities of GUI library design bubble up to developers who are implementing their own tweaks or combinations of a GUI library, usually with a huge amount of “needless” variation. Application developers should ideally never have to be making choices about internals of a GUI system, yet the core of most articles comparing frontend frameworks is discussing GUI internals.

2. There is no golden standard for tooling. Everyone has their pet variations on how to deploy to JavaScript, CSS, and HTML.

3. Back end choice. Huge variation.

As a developer we get APIs on the edges, but we make our own spaghetti to join everything how we wish because there is not one or two standard library/framework choices, and we have the power to do what we will. I developed my own 100% custom component framework because I could write one that suited us far better than what was available at the time (OSS or commercial). Browser variation used to be a huge driver for complexity, but is far less so now.

* drawing primitives can also be Canvas or SVG or WebGL e.g. https://qht.co/item?id=27131659 is a good comment.

[1] https://www.google.co.nz/search?q=lisp+curse


At least in AI, what happened to lisp was being replaced by Python. What do you presume happens to JS in this case? WASM frameworks are likely to have the same problems. Stuff like Phoenix Liveview can be rather standard but limited in scope.


It makes me smile that elsewhere in this thread there's people saying "I've been using <library> and state management is now super easy." when you know in two months people will be saying that library is over-engineered and someone will suggest to try the new panacea that will solve all of your problems, for real this time.

Such is the hype cycle of frontend development.


I mostly use Qt Widgets which hasn't fundamentally changed since 1995 and still performs just fine for desktop UI


Link: https://grugbrain.dev/

It is universally worth your time to read it if you haven’t :)


Plain english translation: https://github.com/reidjs/grug-dev-translation

I haven't read it, but wish I had seen it before struggling through the original


Thanks so much for the link! I tried the original and bounced off the style. It seemed like something that might be fun and useful if I invested enough effort in reading it, but I just bounced off.

But with the translation, I just devoured and appreciated it.


Amazing read! Missed it when it trended 10 days ago.

https://qht.co/item?id=31840331


Server-side templating died for this.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: