Principles and priorities
adactio.com
adactio.com
I've collaborated with many different teams that use the modern JavaScript stack. It seems to me that it takes multiples of time to deliver features compared to the old forms-and-HTML-with-a-tiny-bit-of-JavaScript-enhancement methodology.
Are we really optimizing for developer efficiency here? We've given JavaScript-everything a decade to prove that it's a better, more productive way of building higher quality websites and applications. I don't think it has.
It's trivially easy to hook up a "delete" button such that it works without JavaScript, but if JavaScript is available it turns into a fetch() POST that removes the item (with a CSS animation) once it completes.
Or if you're too lazy for progressive enhancement, you can skip the "works without JavaScript" bit.
I used to do this kind of thing with jQuery one-liners all the time. Today browser compatibility is good enough that you don't even need jQuery.
Oh and the user is logged in and is receiving a notification that an item they were watching is now available, better show a toast.
Sorry but the simple jQuery sites turn into soup once the requirements are what they are today. You can still do it, it's possible, it becomes harder and harder to maintain long-term though. Then efficiency becomes worse than how people do it today.
Look at how many content-oriented news website article pages have gone all-in on React, with the result that they serve up over 1MB of JavaScript just to show you an article with a "save" button that no-one ever clicks.
> First and foremost, there’s the end user. If a technology choice harms the end user, avoid it. I’m thinking here of the kind of performance tax that a user has to pay when developers choose to use megabytes of JavaScript.
I believe the author is indeed talking about React (and other frameworks), SPA, big JS bundles. The developer efficiency being alluded to here is for tech startups to scale a team. A component-based frontend is valuable in providing that efficiency. The efficient is not about building a form in a few hours vs 2 days with React, but about code maintenance and scaling a team so many developers can work on the frontend at once in a sensible way.
However, having said that, I am not an advocate for a React frontend. I actually recently wrote an article, on a different topic, but with a very similar theme [1]. I think component-based frontend framework solves a real problem in an organization, but it does not have the best UX in mind.
[1]: https://dev.to/bigi/dev-to-is-the-perfect-demonstration-of-h...
A couple months in he gave me kudos for getting something done in “only two weeks”
This was work that would have taken less than a week on my first big frontend job and here it was noteworthy that I did it in twice the time. Confusing emotions. Initially I felt dirty. Or like I was in the beginning of a horror movie where it turns out the happy guy is the killer.
And while I agree with the title on the article, I think it’s a shame because what we should be rewarding is effectiveness, not efficiency. I probably spend 20% of my time working on improving productivity and reducing variability for the whole team. Which means I get a little bit faster (and a lot less stressed out) in aggregate while everyone else gets a lot faster. That lead’s boss hired me specifically for that, but not all bosses are so enlightened (and he left a year later).
I worked through the pre-Javascript world, the jquery world, the angular1 world, and now the react world (not to mention a decade of native GUI development before that). I am vastly more productive with react and my UIs are much easier to use.
Every time I submit some 1990s or 2000s era form that gives me an error because I typed some field wrong, but also wipes out half the other fields I spent 15 minutes typing... and of course, hitting the back button wipes out the remaining fields... I want to reach into the screen and throttle someone.
No thanks.
Back button stuff; I mean, it's not trivial to support it correctly now, and it might just be an increased focus on usability and testing of this sort of thing, but hitting back was always dicey -- half the time you'd get some error about re-posting form data when you hit back, and if you said no, bad things happened, and if you said yes, worse things happened.
Back button works every time if you create pages, and navigate between them using links.
There are some garbage web forms out there, but if we're comparing building SPA in 2020 or webforms in 2020, webforms is unlikely to screw up your back button.
That's exactly why we put so much effort into making sure Django's forms framework didn't wipe out the values you had already filled in if there was a validation error.
The problem you describe is solved by frameworks like Rails, and has been for at least 10 years.
It turns out there's no need to bring in hundreds to thousands of JS dependencies to implement your frontend. SSR gets the job done in a superior manner, both in DX and UX.
When a programmer says "I am vastly more productive" then I know the project is vastly over budget, vastly missed all deadlines and has a vast headcount delivering something vastly unusable.
Programmer feels on their own 'productivity' are inversely correlated with real-world project productivity.
This is because programmers love to code, so more code and more complex code == 'productivity', while in the real world code is a liability, not an asset. The less code in a project, the better.
Today's apps are immense JS programs - tens if not hundreds of thousands of lines.
Good luck scaling that without modern tooling.
If the thing you are building needs that then go ahead and build it like that. But SO MUCH of what I see built on the modern JavaScript didn't need to do that at all.
A lot of websites were converted to this paradigm during the pandemic because the initial UX was that the site got DDOSed by legitimate, high load, or hacked.
And this is from quick conversion (e.g. scraping a dynamic page, Wordpress plugins, etc). I think there's a lot more potential when sites are built with the static paradigm in mind.
My personal blog for example is created by a static site generator I wrote in Rust myself. Instead of manually writing HTML, or using PHP and Javascript at runtime, I handle the complexity at build time. After having done frontend dev for 10 years this approach seems much more sane to me.
A sign-up form? Yeah, you aren't getting much from your SPA framework. Pure overhead.
A data-table with user-selectable columns, pagination, and arbitrary sorting and filtering, where the data is too large to fit in memory (billions of rows) so you have to re-render by hitting the server; but the rows contain view-state components, so you can't re-render on the server? Two lines of code in an SPA; three months on your own. Equal resulting JS size, either way.
And something like Grafana: how would you even do that server-side? Emit a server-sent-event stream of SVG images? This is a case where server-side rendering would result in heavier client-side code than an SPA would!
-----
Now, the majority of people using SPAs don't need SPAs. I think people get into SPA frameworks like React because everybody wants to learn the frameworks and libraries, to have them in their pocket and on their resume, for when they (hypothetically) one day get hired for that one job where they do get to build the fancy slice-and-dice analytical data dashboard. That job probably would pay pretty well. They want to be qualified for that job.
If you're a project manager, and you really value getting an MVP shipped quickly, you should push back on the engineering lead's desire to use an SPA framework. Ask them whether there's anything they're really gaining for this specific project. If there's no reason not to, then just suggest they build the app as a plain-old server-side-rendered-HTML app. Use Rails; heck, use PHP. (Or be fancy and use Phoenix LiveView.)
Good question, we’re really not, we’re optimizing for making websites and webapps work and feel like desktop apps.
>We've given JavaScript-everything a decade to prove that it's a better, more productive way of building higher quality websites and applications. I don't think it has.
Not unless you count things like Google Maps, which wouldn’t be possible without SPA-style JavaScript.
Most of the things I've seen built using the modern JavaScript stack don't warrant working and feeling like desktop apps. They should work like fast-loading websites - especially on mobile phones, which is the source of most traffic these days.
I think it might just be a matter of what feels like home to you.
I take my own software that I write solely for personal use as examples. In those cases, I play both roles of the developer and the end user. Most of my utilities are console command line utilities instead of full GUI. As a result, I have a bunch of command-line utilities that are very cumbersome to use. That's because I prioritized the dev experience over the UX.
Console apps are 10 times faster to code. I can bang out printf() or Console.WriteLine() statements 10x faster than placing GUI textboxes on a form. Yes, GUI wizards and templates accelerate the layouts but it's still not as fast as console apps for quick & dirty utilities. As an end user, I'd prefer easier-to-use GUI apps but I don't have the extra time to code them. I complained to the developer (that's me) to make a GUI app with better UX instead but the dev ignored me.
With my limited time, I'd rather have 20 utilities with bad UX that exist rather than just 5 apps with good UX at the expense of not having the other 15 at all. It's an unavoidable tradeoff of finite time.
Likewise, I as an end user don't like Electron apps but I know that lecturing developers on using something lighter weight like C++ & Qt or C#/Winforms means they wouldn't bother writing the app at all. It was the ease (and/or familiarity) of Javascript that allowed them to write the app in the first place.
[REVISED above text to clear up the misunderstanding in the reply.]
> Most of my utilities are console command line utilities instead of full GUI and they are very cumbersome to use. That's because I prioritized the dev experience over the UX.
As the user you prefer command line utilities, and so I interpret your building command line utilities as prioritizing the user's experience.
On the other hand, if you needed a program that could exist very efficiently as a command line utility but, desiring to learn how to use some new GUI toolkit you built a GUI instead, I might interpret your action as prioritizing the developer experience (in which you are focused on the details of the implementation) over the user experience (in which you are focused on the results).
Except this is obviously untrue? I can't pipe a window through grep or sed.
For utilities I won't use very often I just hard code the parameters. If I want different parameters I edit the code.
Same here, although lately I don't even bother writing a full CLI utility. Instead I just write a few functions to call from a REPL.
(On a side note, why is the REPL experience so bad in JavaScript? How can Clojure have a better REPL to the JavaScript ecosystem than JavaScript itself?)
But it points to a problem with using the word "efficiency" like this if it's so commonly misused/misinterpreted.
"Deliver value" is something I've seen people push instead, and it tends to stay more customer-focused. It's hardly perfect, and there are still temptations to bikeshed and focus on the wrong thing, but it's a bit easier to recognize and course-correct as a team when that's your ultimate goal.
Just adding faux-numerical terminology helps a bit: ideological debates are of (approximately) zero value, whereas javascript frameworks are of negative value.
> "Deliver value"
TFA did already make this point, but that's meaningless unless it's short for "Deliver value, even it conflicts with [some specific other thing that you might resonably want to do].".
And eventually you will start hearing them complain about an unmaintainable mess and turnover will probably increase.
/s
I think you do have to care, on some level, about maintaining code quality and standards. I've worked in feature-factories and it's not a panacea. It doesn't crash and it goes reasonably fast are both features after all that seem to be related to the quality of a code base and the expertise of the team behind it.
For instance: first week of the iteration is for paying off debt. Second and third are feature work. Fourth is testing (note: not unit testing, real testing. As in everybody chips in to actually play around with the features their colleagues added and provide feedback; also verify that all the bugs that were fixed this iteration didn’t creep back in, or get fixed with a “works on my machine” patch)
2. As the real customer for the developers consists of these institutions, they care more about development costs than whether customer internet is wasted. Developer convenience means cheaper projects.
3. Users blame themselves for the performance tax. They think they downloaded a virus, have an old computer, or need faster internet and they go and upgrade all those things, making the performance tax seemingly disappear.
This is extremely reductionist.
If you want to take it further, then nobody works for the end user ever. If you have any funding at all (even from the public markets) then you "work for investors".
Can you see how this is theoretically true, but practically not as true?
And part of the way you can actually deliver a good customer experience, consistently, at scale, is by focusing on developer efficiency. To consistently deliver a great experience to customers in a world of constantly shifting customer expectations, you need to be able to ship features from design through delivery very quickly.
This means enabling your developers to be more efficient by designing products that are flexible. Maybe the user experience isn't 100% optimal for a given customer interaction, but the goal is to keep the sum of all interactions over time as high as possible.
Maybe the OP's argument doesn't fit every case, but there's many where it does (e.g. large companies). Calling it reductionist, doesn't necessarily invalidate it...
If you work for a web site that makes its money by lead gen or advertising, you're often working against the end user. This isn't necessarily true, it's just how the incentives will align.
If you sell SaaS to the enterprise, you're not working for the end-user, you're working for their boss, or whoever else is making the purchase decision.
If you're selling a product directly to end users, and usability is a factor in whether or not they choose pay you, that's a little closer to working for the end user.
And, best-case scenario, if you are the end-user, or your boss is the end-user, then you can truly be working for the end-user.
End user interests are different then buying manager interest: software that can tick all the checkbox, has all the features, but is hard and unpractical to use. Buying managers dont know they are buying crap and typically dont listen to low level employees who have to use the software. Instead, buying managers put pressure on whether checkboxes are ticked and price.
Company that develops software is interested in getting it out cheaper and in pretending checkbox is ticked. Where buying manager really want checkbox ticked, employer wants minimum cost way to do it. They are juggling multiple customers with incompatible requirements. Plus, managers are interested in their own departments and own empires in expense of overall product.
By the time developer gets assignment, end user matter only little. And developer does not have any way to even learn about his pain points and much less have time to do something about it.
Like it or not, titles dominate discussion. The comments in this thread are nearly entirely a reaction to that title. The HN guidelines specifically ask users not to abuse that power. On HN, submitting an article doesn't confer any special right to frame it for everyone else.
If you want to say what you think is important about an article, please post it as a comment to the thread. Then your view will be on a level playing field with everyone else's: https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
If it's necessary to change a title, please do that by picking the most neutral and accurate phrase you can find on the actual page which represents what the article is about. More on that here: https://news.ycombinator.com/item?id=22932244
So it seems expected that the agglomeration of tools with varying secondary goals, and a clear primary goal, results into this goal of developer efficiency being potentiated greatly. Forget about writing 5 lines of code, just npm install it.
And that is fine IMHO, people/companies with different goals should be doing things differently. It also seems that turnover is a big issue as well for most companies, so they also try to make dev experience better!
>Usability is more important than profitability.
For a bootstrapped company in danger of running out of money, it's ridiculous to prioritize perfecting UX over making sales. For an open source team, profitability isn't part of the equation at all but user experience might be a top priority. My point is, these aren't just matters of personal taste, the "design principles" have to mesh with the rest of the organization.
One you have easy to understand code it is easy to understand how it needs to be modified to make it work, right, fast and or pretty.
Long term: developer experience, even over user experience, because over a long enough time period developer experience drives user experience.
I strongly disagree with that, "modern" web development values beautiful code over almost anything else, if that wasn't the case you could have one of your dev building a form in a few hours, instead they need tons of tools (react for example) that slow their development
Web programming and the web has separated developers too far from the hardware that actually runs the stuff and, as a result, we have built confusing towers of babel.js.
I mean, Javascript was originally made for developer ease over user reliability - and look at it now - it shows with the cacophony of NPM dependencies prone to "leftpad" style failures and the new frameworks every 6 months. All of this, of course, goes against one of the author's key points: "User experience, even over developer experience."
Unfortunately, I don't think the problem is solved by process but instead on re-education to compiled, reliable systems, made with a typing system designed to catch errors. Introducing more process and efficiency will never make a bicycle into a proper car.
We already have that in the form of TypeScript, but both left-pad and core-js were, for lack of better term, non-technical failures.
Only the most recent such case - is-promise - was purely a technical failure.
There's not much than can be done when the sole core maintainer of a popular library lands in a penal colony.
While an improvement Typescript is a far cry from the likes of Ada and doesn't really compare.
> There's not much than can be done when the sole core maintainer of a popular library lands in a penal colony.
Perhaps the solution is to not use Javascript, since it always forces you into an "ecosystem" of "frameworks" at every turn - and they are not cheap! Just another thing to throw on the stack. mb's be damned.
Given their respective popularities perhaps the point of diminishing returns was crossed somewhere?
> Perhaps the solution is to not use Javascript, since it always forces you into an "ecosystem" of "frameworks" at every turn - and they are not cheap! Just another thing to throw on the stack. mb's be damned.
This is becoming outdated information thanks to the likes of Svelte:
and Solid:
I would condition this to be:
> "modern" web development values beautiful code _that you can see_ over almost anything else
I wouldn't call apps that are run by transpiling code into another language so that it can be compiled into something else, that is packaged up and shipped around in a docker 'image' and then run in who-knows-how-many levels of virtualization in someone else's cloud, particularly beautiful.
I contrived a painful example, but if we're talking 'beauty' in terms of what you see in your IDE/text editor, then maybe you're right, but in terms of what an application is and how it's used/deployed? No way.
> But as a general principle, I think this works:
> User experience, even over developer experience.
>Sadly, I think the current state of “modern” web >development reverses that principle. Developer efficiency >is prized above all else.
My problem with this isn't that it places value on user experience, it is in the premise that developer efficiency is prized above all else. Deploying an app today is just as hard as it was 15 years ago. The only two things that jump out in recent memory that made a very sizable difference on developer experience were Heroku, Github, Docker. Setting up a hello world with react and a basic API takes me a day or more, where as 10 years ago with jquery this was an hour or so. Deploying an app with K8s is google scale, but takes me a week to do, forget debugging something in production.
If we've been prioritizing developer efficiency at all costs we've failed pretty massively. I personally love the idea of optimizing a lot for developer efficiency because we can do deliver more value to others at the end of the day, but there's a lot of shiny new stuff that has some reason for existing which is definitely not developer efficiency.
Do we not hear all the time on HN, for example, that "Yeah, native apps are more efficient and look better but Electron lets us just write it once and deploy on multiple platforms"?
Electron is one of a number of technologies which allow things to exist (in a non-optimal form) that might not be economically possible if a bigger team or a lot more time were required to ship them.
IMHO the sad thing is not that Electron exists, the sad thing is that we don't have stuff that's way easier like hypercard or VB6 was.
A toggle? Yep. A timeline? Yep. A textarea? Yep. Toasts? Yep. Spinners? Yep. React just has so many pre-built components that you can add features very rapidly.
Continued correct activity of OS processes is prioritized over user-level activities even where the purpose of the system is explicitly the latter. The reasoning seems to be that if the OS can't keep up, it can't maintain the environment that enables user-level stuff to work.
This generates conflict where user-level activities have real-time requirements. It is very, very hard to get your typical OS to leave a process running on a dedicated ("isolated") core and never, ever interrupt it, even given root privileges and boot-time static provisioning. Just store a byte in a file-mapped page, and whoops! get unsynced millisecond pauses while the OS copies it to the disk sector. Oh, and surely you still wanted an interrupt every millisecond to see if any OS resources tied to the core need cleanup, even though it never is asked for OS work.
Most programs need to run on the OS they need to run on, and on the hardware they need to run on. QNX (or other favorite obscurity) most usually is not an option.