How the fuck did we get here? A small rant on the "modern" front-end
fagnerbrack.com
fagnerbrack.com
This is the price you pay for the convenience of not having to write all the stuff. Yeah updates suck and it sucks people don't maintain their libraries better or write them better to begin with but people have lives and may be doing this stuff on their own isn't sustainable beyond a point.
The solution could be "less people make libraries" or it could be "more people make libraries and more people help maintain them" or it could be that people who make apps stop using libraries and write the code themselves.
You can't force people to maintain every piece of code they put online just in case someone uses them in one of their apps then a year later wants to update their app. What if the end user wanted a different specific version?
This stuff annoys me as much as anybody but whining and posting it to hackernews is just self-flagellation.
Its the difference of not paying for the stuff.
In the past you would pay a vendor and they would give you libraries and provide bug fixes and vulnerability patches.
Unfortunately the way dev compensation works (i.e. mostly salaried with big jumps possible from job hopping), we're all very incentivized to go with free stuff today even if it actually turns into a major source of tech debt tomorrow. After all, if you're paid by the hour does it really matter if you spend days or weeks fighting with abandoned dependencies? It matters to the company but to the individual it can even be a benefit, because you get experience with things that look good on the CV. That in turn damages the market for developer tools, creating a self-fulfilling prophecy where not many people try to compete against free, so people conclude it's just the natural state of things and can't be any better.
I see this problem with my own product: our customers mostly come to us in a sort of shell-shocked state where they've lost a lot of time and hair trying to make the available open source tooling work for them, and decide to buy ours as a sort of last resort. Then they get it all working, we help them fix any issues, they have a good experience in the end and are happy. Unfortunately people have to go through that bad experience first because everyone's initial instinct is always to go with the free stuff, and indeed they probably won't even find out about the alternatives because there's a culture in which open source projects only want to advertise or integrate with other open source projects.
So the author asks, how did we get here? That's how.
There's other ecosystems like Java+Springboot where you can go 2-3 years only doing minor/patch upgrades without too many changes.
React is on version 18, released in 2011. Springboot is on version 2, released in 2014.
>Oh no, this free stuff I got wasn't good enough
And then other devs feel the need to use the package rather than copy a code snippet.
The fact that "is-odd" exists is just silliness. It's a joke. The fact that it has nearly half a million WEEKLY downloads should absolutely horrify you. Any developer that uses the "is-odd" package is wholly unqualified to be coding and needs to get a refund from boot camp that "trained" them.
Using is-odd is fine, the same as developers using the "+" is fine in languages that support it. Where JS is weird is in not having a full standard library along with very arbitrary data, leading to folks seeing that they use the is-odd functionality regularly enough to where it's useful to have a dedicated operator
I'd use an is-odd library if I need to figure out if something is odd across 20 different data types depending on how somebody inputted data in a UI
Whenever I see people say things like “we are back where we started with file based routing” I see it more that we’ve remembered what was good about the old days and cherry-picked that good stuff.
It's less that people take issue with JS/TS itself and more the frameworks that use it and the associated dependencies and tooling. The complaints in the article are very representative of my experience.
I actually always tought of web frontend to be the easiest to start with. But that only applies to starting a very simple project from scratch without external dependencies. Afterwards the complexity grows very, very steeply.
Starting new fully featured web project takes me whole day. And if I want to use recent version of the stack, everytime I have to forget everything I knew and start again, because everything changed totally since I did it last time.
The fact that some newbie would upload is-odd[1] to npm doesn't surprise me. The fact that it has half a million weekly downloads - it's blind leading the blind.
And framework complexity - I find that consistent with mid level programmers being fascinated by complex solutions and top scale teams needing to deal with the pile of shit they are building on (DOM/JS)
Archive Today: <https://archive.is/QZ3AO> (I'd submitted that, which suggests that the problem is in my own Web configs...)
Wayback / IA: <https://web.archive.org/web/20230407211857/https://fagnerbra...>
Google Cache: <https://webcache.googleusercontent.com/search?q=cache:https:...>
I also think "not invented here syndrome" is not (always) bad. A piece of your own codebase instead of a 3rd party library can have less maintenance cost even if it's a often reused piece of functionality. I always deliberate on adding just another library even if it's just one npm install away.
• A simple Compose CRUD app that connects directly to Postgres using its native protocol. Users log in to the DB as themselves.
No web servers, no HTML, JS, CSS, REST, JSON or even HTTP. Just Kotlin and a bit of SQL to setup the schemas and object security. jOOQ auto-generates language bindings and type safe SQL API by reflecting the database.
• A drop-dead simple workflow for deploying the app and updating users.
Just like a web app the entire release process (bundling, packaging for each OS, uploading, icon generation, even making a download page) is done with one command. Users update to the latest version every time the app launches, like a web app would update. I'll be demoing how quickly this can be set up and done with Conveyor (my own product, natch), and you can do it all from your laptop.
• Visual layout design.
Just like React, Jetpack Compose doesn't have a visual UI designer. But there's a cunning trick. Using the JavaFX Scene Builder and GPT-4 you can convert FXML to Jetpack Compose Kotlin code, giving you a nice designer that helps you quickly rough out a layout visually and then use it even from a totally different toolkit. I used it to help develop the demo - mind blowing stuff!
Obviously nothing about any of that is Kotlin specific, you could do the same with any language that runs well on the desktop. At some point I hope to make a similar demo with Python using GraalPython (why jvm - because it has mature portable UI toolkits, very mature SQL libraries+db drivers, is easy to deploy to every OS from your laptop and has the best language interop).
I wouldn't try to make the next Instagram this way but for the apps that fit the advantages are numerous. The code for this demo is simple because leaning in to your RDBMS gives you so much functionality for free that you'd end up duplicating in an ad-hoc and often bug-prone manner on the web. Almost all the code is UI logic.
Historically distribution was the sticking point and something Delphi/VB never really solved once you got beyond "stick an exe in an SMB shared folder". Conveyor solves that which is why I'm doing the demo, to advertise how resolving a developer usability bottleneck in one area allows you to increase usability in other areas too.
Rails is very fast to get started with but I find it unmaintainable for anything that lasts longer than a few years due to being untyped.
AdonisJS seems like a much better option to go with today as it picks up a lot of the conveniences of Rails while being TypeScript.
No it's not. It costs nothing to not write defensively, especially in an untyped language. This can easily be an article about Python as well.
By not paying people to maintain critical infrastructure?
Ah yes, the old days of C and C++!
Where if you were lucky enough to get the sources to a library (hah!) you spent a lot of time adapting it to your platform and build system and then you never ever touched it ever again.
Granted things used to be easier when the only code relied upon was the OS Platform UI library, which had the benefit of being well tested, and any flaws in it well documented, since new releases only came out when a new version of the OS shipped to actual physical stores.
Now granted, the JS ecosystem and the dramatic changes in modules and exports and stuff has been particularly bad. I was trying to import a library from NPM that was ~5 years old and I gave up and just... copied the code into my source tree and imported it that way.
More things change and all that.
https://bundlephobia.com/package/htmx.org
roll safe, kids
Maintainablity? Sustainability? Fergetaboutit.
Now, to address the question of how we've reached a point where software dependencies often seem unstable or difficult to manage, I believe there are several factors contributing to this situation:
Rapid pace of technology and innovation: The web and software development landscape has evolved rapidly over the years, with new tools, frameworks, and libraries being introduced constantly. This rapid pace of innovation sometimes leads to a lack of focus on long-term stability, as developers may prioritize adding new features or keeping up with trends over ensuring backward compatibility.
Increased complexity: The web has become increasingly complex, with new technologies and standards being introduced regularly. This has led to a more complex ecosystem of dependencies and interdependencies between packages, making it harder for developers to maintain and update them.
Fragmentation of the ecosystem: The JavaScript ecosystem, in particular, is highly fragmented, with many different libraries and frameworks available for similar tasks. This fragmentation can make it difficult for developers to select the most stable or well-maintained option, and it can also contribute to the "cascading effect" you mentioned when updating one package leads to the need to update many others.
Shorter project lifecycles: In the fast-paced world of software development, projects often have shorter lifecycles than in the past. This can lead to less emphasis on long-term stability and more focus on delivering features quickly, even if that means introducing breaking changes more frequently.
Open source community dynamics: Open source projects are often maintained by volunteers who may not have the time or resources to ensure long-term stability. Maintainers may also change over time, leading to different priorities or approaches to stability within the project.
Vanilla JS have been perfectly tenable for a while now. No, you don't need to use React.
According to Algolia, at this writing, the words "how did we get here" appear in HN submissions (net of flags and edits) 363 times. That's exceeded by the even more tiresome "this changes everything" (571 results). Both should be hellbanned IMO. I'm having an email exchange with dang over this presently.
<https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...>
<https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...>
On your own blog, to readers familiar with your topics and post history, "how the fuck did we get here" might be an acceptable / excusable title, though even there, I'd argue that it's a rather poor pick. It's a bit like dropping a URL or video link with the comment "lol" on an HN or Metaverse thread, say. There's not much to go on.
Even pretty good bloggers often have ... depressingly unilluminating titles. Brad DeLong, for example, leans very heavily on "Why Oh Why Can't We Have a Better Press Corps" (you'll find a few examples perusing <https://braddelong.substack.com/archive?sort=new>). Several people on the Fediverse post frequent themed items, with a repetitive title leading the description, e.g., "Plucked from the archives <description>". My suggestion is to invert that order, have the description first, and probably hashtag the topic as, say, #FromTheArchives.
(I do something similar with "#OccasionalEtymology" and "#DredsDictionary", see:
- <https://toot.cat/@dredmorbius/tagged/OccasionalEtymology>
- <https://toot.cat/@dredmorbius/tagged/DredsDictionary>
There's a reason why article authoring and headline writing are often distinct roles at traditional serial publications. What it takes to write copy and to sell it (via the headline) really are separate skills.
Nielsen's microcontent guidelines: "Microcontent: A Few Small Words Have a Mega Impact on Business" <https://www.nngroup.com/articles/microcontent-how-to-write-h...> (2017) (Based on a 1998 original.)
Your encouragement, however, changes everything!
;-)
dependency management is hard
Semantic Versioning is permission to break things. As Rich Hickey would say, just use a new name [1].
[1] Rich Hickey - Spec-ulation: https://www.youtube.com/watch?v=oyLBGkS5ICk
Ideally, before someone decides to inflict their open source code upon the world, they should at least nominally commit to 100% backwards API compatibility. That sets the correct frame of mind, both as a maintainer but also wrt designing and implementing your API. For example, these days all new syscalls on Linux are expected to have a flags argument and strictly reject undefined combinations of flags and arguments. There are exceptions, but that's the baseline expectation; even when excepted, those expectations help steer the conversation to expose potential compatibility traps. And they do this because Linux nominally promises 100% backward compatibility, regardless of versioning; though it took them many years to appreciate the need for those particular technical guard rails.
If and when you need to break your promise of 100% backward compatibility (as even Linux occasionally does), then use Semantic Versioning to help smooth the way and set expectations. (I'm agnostic, but certainly semantic versioning was normative long before "Semantic Versioning" existed.) But if your answer to API compatibility starts with Semantic Versioning, then I wouldn't want to have anything to do with your library. It's like asking a bank what their approach to risk management will be and they answer, "following regulatory guidelines". It's not actually a substantive answer to the question, and suggests that one should avoid that bank.
Semantic versioning said to stop basing version numbers on what version of the software you're talking about, and instead use them to indicate that you just broke everything. This only makes sense if it becomes OK to break things. That was an assumption that semantic versioning brought us.
What it actually delivers:
- 1.2.changed -> don't care
- 1.changed.0 -> don't care (at least I'm not supposed to have to care)
- changed.0.0 -> you're screwed (maybe, on you to check)
SemVer is an agreed upon way to ship breakage.
Things broke all the time, the default expectation was that _something_ would need work, it was just a matter of how much. Semantic Versioning just gives us a framework to (try) to know in advance how much work it would be.