At a high level, why is there more churn in Javascript than in Clojurescript?
The Clojure community, broadly, favors stability and incremental growth (accretion), and to avoid breaking changes. Both in the core language itself and in most of the libraries used. I get the impression that the JavaScript community seems to favor novelty, and always looks to the newest and shiniest thing in libraries and frameworks. I'll be interested to hear what frontend folks say, esp. those who've spent a lot of time in both camps.
Sean perfectly described the "why" (well, IMO anyway), I can just add the "why-why": • Prioritizing DX over UX, when it comes to both the end product with its end users and to libraries with other devs as users • Unreasonable trust in tools like semver, tree shaking (which cannot in principle be reasonable when the first item applies here as well) • Prioritizing dependencies over own code, which plays "nicely" with above items • Upstream breakages lead to devs downstream willing to update more often so that they can fix 10 breakages every week instead of fixing 500 breakages at the end of the year It all essentially leads to situations where devs largely don't care about breakages they introduce. Some do, of course, but they're a minority. Even important industrial software will have breaking changes on even minor releases, often necessitated by nothing more than API aesthetics. And it spirals up from the very bottom - no way I can guarantee the code that I wrote for a today's version of browsers/node will work on a future version. Just randomly checked Node v22 vs. v24. They renamed a few options, then wrote 360 lines of code to automatically rename those options in user code bases, which cannot in principle work everywhere in all scenarios. https://nodejs.org/en/blog/migrations/v22-to-v24#example But I guess kudos to them for not renaming the fields outright and providing a 5 year window between documenting the deprecation and renaming the keys.
Oh man, I'm my worst enemy because now I'm reading about all this crap and I want to become a farmer even more.
Just check this out, it makes me sick: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring#differences_between_substring_and_slice
Just why?!... And of course, there's also a deprecated substr.
To add to my first message above - yet another root cause is the lack of "the" JS. There's the standard and there are implementations, and sometimes they don't agree with each other because people behind the standard and people from specific industries with real-life needs are usually different people, which leads to stuff like this: https://blog.mecheye.net/2017/09/i-dont-know-who-the-web-audio-api-is-designed-for/ Then there's an incredibly slow reconciliation process, with multiple deprecations and breaking changes, with 15 different libraries all tackling the issue in different manner, with polyfills and tools like Babel trying to close the gap in a unified way.
I think many of the JS community think of themselves as innovative and are, in their own way, striving to implement a framework that is simple, fast and reliable on a language where that is a genuine challenge. They'll eventually get something like Clojurescript 😅
While it could be true, the issue is pervasive - it's not just frameworks. Every tiny library is an issue with high probability.
Thanks for these thoughtful responses. It seems breaking change is a big one. I remember Rich talking about change in the "Spec-ulation" talk. He said that one-sided change is theft. I suppose this is a breaking change that takes time and effort to fix. But is there something intrinsic about Clojure/ClojureScript that means it does not need to be changed much? I suppose there was a lot of thought in the design of it that might reduce the need to change. This is good enough? Yeah, the habits and philosophy of a community perpetuating churn is interesting. I suppose the gurus of the community set these norms. In Australia, we have a national curriculum (standards) that seem to create a bit of churn in curriculum resources. There are some breaking changes, but there is also something rotten at the core of the curriculum itself (e.g., many vague and difficult to interpret standards displayed in a confusing format) Maybe I am trying to see if something can be learnt by Clojure community.
Epistemology is a big problem, especially as the content of any curriculum is subject to more and more contention.
@raymcdermott sorry I don't understand. I am pretty agnostic about whether a national curriculum is useful. I just think if we have one, it should be clear and not proliferate churn of curriculum resources etc
> there was a lot of thought in the design of it that might reduce the need to change It is indeed a big factor, but not the only thing. Even if some language is designed perfectly, times change and old designs become obsolete in the presence of new ideas. So by itself design doesn't guarantee anything. The bigger factor is the fact that avoiding breaking changes at (almost) all cost is one of the values of the core team, and by extension of the community. There are plenty of things that are part of Clojure that would've been approached differently were they authored today. But they remain the same, at least where their users are concerned. New things might come and make the old ones obsolete - but the old ones are still not removed.
That is interesting a core value that reduces churn
> Even important industrial software will have breaking changes on even minor releases, often necessitated by nothing more than API aesthetics. Yeah, I've witnessed tons of breaking changes in popular libraries and frameworks because of aesthetics, usually to be consistent with the naming of new functionality. It's ridiculous. But then, most consumers seem to think it should be so, so they don't push back.
There is also the concept of transitive dependencies, which does not help at all, and semver which tried to fix the issues with transitive dependencies, which it fails spectacularly at. (the result being indeterminate systems, from install to install)
Shrinkwrap was added as a fix to that again. (which is now lockfiles). That's a pretty long chain of problems and fixes, imo.
@gar so some design decisions are creating self-reinforcing churn, but there is also no pushback to constrain the range of possible solutions.
That's just my impression, so take that with a grain of salt.
Of course related to some extent to what has already been said above about community values and priorities, but the integration with the Google Closure Compiler architecture imposes some constraints that, in my view, run both counter and parallel to the direction of the JS ecosystem.
Can you elaborate?
AFAIK all of these explanations are anecdotal. To my knowledge nobody has sat down and impartially figured out what the actual causal factors are here.
Not saying its not useful or the best understanding we have, just lamenting this world
JS is fragmented as people have observed, there is no unity at the level of the language, the target runtime, or even the tooling and the shape of the software artifact (i.e., CJS, ESM, &c.) But JS seems to align itself with the mainstream at least in the sense of "why build it if it's available to you as a dependency," which is not very Clojure-y, in my estimation. I see people here recommend the opposite all the time. And then there are the practical considerations of which NPM packages GCC swallows and which it chokes on
> To my knowledge nobody has sat down and impartially figured out what the actual causal factors are here. I would suggest, politely, that maybe the results wouldn't be very interesting, however rigorous the experiment.
Being tied to GCC makes ClojureScript akin to Python in the batteries-included stdlib sense, however limited that analogy is, which is almost entirely antithetical to the very design of JS at the language level: half-baked, almost no stdlib, but we are gonna lean heavily on third-party libs and a different language altogether being marketed as a gradual typing helper
> I would suggest, politely, that maybe the results wouldn't be very interesting, however rigorous the experiment. I agree on this specifically, but I disagree more broadly. The coding world has 50 PhDs for sociology majors hidden in it
Oh I am in agreement with you there, I am significantly more interested in thinking about the culture and psychology and sociology of programmers than the economics or engineering of software
But it's important to note as you do here that this is more of a sociological question, because that implies (at least it seems so to me) that subjecting it to the typical scientific framework of this-then-that causality would be grounding the problem erroneously
I suspect a lot of JS devs just accept this as the status quo and are not familiar with ecosystems where there is a lot less churn. There are also a lot of people who look at (widely-used) Clojure/Script libraries that haven't been updated in years and consider them "unmaintained" rather than "done".
Programming is a status quo discipline with very conservative (though maybe not for all that coherently elaborated) standards for "when X thing ought to change"
@bhlieberman93 https://leif.me/upcoming-paper-jam-the-psychology-of-software-teams-part-1/?ref=working-together-through-computers-newsletter sounds like it might interest you?
for sure, thanks @seancorfield
Java is the other example that's closer to home
Java the language and sdk, sure, but not so about libs and frameworks. At least Spring has been quite notorious with breaking changes, starting with a complete rewrite and total breaking change going from v1 to v2 (if I remember correctly). Stumbled upon this recent study, while trying to find a summary of Spring's breaking changes through its history. Highly relevant to this conversation: Breaking Changes in Software Ecosystems: A Systematic Literature Review https://arxiv.org/html/2605.24397 > In npm, improving API design alone accounts for 939 of 1,519 cases (61.8%). Reducing code redundancy (469, 30.9%) and improving identifier names (111, 7.3%) cover the rest [S1]. So back to @p-himik’s often necessitated by nothing more than API aesthetics, then.
JS Fatigue: The one thing I hate the most. There almost nothing you can't do with React (browser) 10 years (okay, 8 years) that you can do now. Except bundling, I agree that's been helpful. But other than that, it's just conventions, paradigms, etc., forcing you to learn "new" stuff every year. I even have this impression that FAANG companies have idle budgets lying around waiting for someone to pull them out, so they go like "hey, I have this idea for a new JS framework, want to allocate some money for this please?" and there they go again..
I'm maintaining a project that still uses Material UI v4. Some years ago they released v5, I checked the release notes, got floored with the amount of breaking changes and with next to no improvements that would be relevant to me, and decided not to upgrade. A few years later, we now have... v9. God damn. Release cadence: v1 - 2018 v2 - doesn't exist v3 - 2018 v4 - 2019 v5 - 2021 v6 - 2024 (woo, 3 years!) v7 - 2025 v8 - doesn't exist (or maybe it's closed-source) v9 - 2026 So pretty much every year its users are expected to rewrite everything, because their humongous release notes consist almost exclusively of breaking changes. Eye-balling it - roughly 90% comes from superficial API changes. Component renames, property renames, nesting changes. Bloody hell...
I was faced with the same upgrade. A total shitshow. Ended up migrating away from the library, creating our own component library instead. It was a long and painful process (part of that was our own fault, as material-ui code was everywhere in the appcode, instead of being encapsulated within components - something we rectified with our migration)