Hacker News new | ask | show | jobs
by Silhouette 1860 days ago
There's nothing stopping you from doing it, but part of the reason a library like React achieves such widespread use is the ecosystem that builds up around it, and if everyone else is using hooks to expose whatever functionality they're building, you are now excluded from the benefits of all of that work.
1 comments

Well sure, if you don't adopt the new technology then you don't get the benefits of the new technology. But that's true it literally every ecosystem. If you don't upgrade to a C11 compiler, then you can't use libraries using C11 features either.

But in both cases, there's little reason not to upgrade because your old code will still work fine on the new version. And indeed you're free to continue writing new code in the "old" style. Adding additional API surface after 3 years while continuing to maintain and support the old API is hardly unstable!

But that's true it literally every ecosystem. If you don't upgrade to a C11 compiler, then you can't use libraries using C11 features either.

I don't think the situations are equivalent, at least not to any meaningful degree.

With C11, your old code continued to work, your old libraries continued to work, your tools probably required at most minor configuration changes, your new code and libraries were still mostly the same style even if you also used some of the new features, and anyone you were working with who knew one version could very quickly and easily adapt to the other.

With React, you can stop after your old code and libraries continuing to work, except that you might not be able to use those old libraries from new code any more and they might no longer be getting much ongoing development. You still effectively have to learn a whole new version of React API, and find your way around a whole new ecosystem of libraries and tools that operate alongside that new API. So does everyone you're working with. You have the backward compatibility, but only by having two completely different coding styles in the same code base, and if you're hiring new people who only know the new API and ecosystem, they now have to learn the old one as well to work on your code.

If the original point was about whether tools are stable for a long time so you don't have to worry about making major changes or learning big new things, one of these situations is not like the other.

The fact that you can have different coding styles and APIs in your project and it will work is proof that it is backward compatible.

And, this is to be expected, because the React Core team prioritises backwards compatibility as one of the key features of the library. See: https://reactjs.org/docs/faq-versioning.html#commitment-to-s...

This is why features and deprecations are announced years in advance of the changes and that when code to support a feature is eventually removed they produce a compatability polyfill in order that teams do not need to do big-bang rewrites (e.g. https://github.com/reactjs/react-lifecycles-compat).

Maybe you disagree with what backwards compatability is? It doesn't mean that new features are backported to old verions of React or that the recommended syntax/API never changes. It does mean that you can rely on modern versions of React being able to run code you wrote 5+ years ago.

I find complaints about the stability of JavaScript kind of ridiculous. Everybody is literally still transpiling down into ES5 (2009) and most only dropped IE11 this year (2013), the main libraries/frameworks tend to make expert use of semver, polyfill old APIs and release codemods to automaticallly perform syntax upgrades. I'm interested whether there are any programming language ecosystems that have done this better? As far as I can see Python 2 to 3 caused hard rewrites, etc.

The fact that you can have different coding styles and APIs in your project and it will work is proof that it is backward compatible.

I don't think anyone is disputing that React is still backward compatible with the old API. The point is that there is a difference between having two APIs that both still work and having one stable API.

Backward compatibility is implied if your API is stable, but that's only one aspect of stability and there are many other practical questions. Will documentation and tutorials from a few years ago still be relevant? Will someone joining your team need to learn anything different before they can be productive? Will other libraries you have used previously that integrate with React still work with your new code? Will new libraries you might want to use today that integrate with React work with your existing code that uses the old React API?

Having multiple integrations with different APIs or different libraries to do the same job is a form of technical debt, and sometimes it can become quite expensive.

I find complaints about the stability of JavaScript kind of ridiculous. Everybody is literally still transpiling down into ES5 (2009) and most only dropped IE11 this year (2013), the main libraries/frameworks tend to make expert use of semver, polyfill old APIs and release codemods to automaticallly perform syntax upgrades.

Well, there are a lot of things you've said there that aren't quite the whole story.

A lot of modern build processes don't just target vanilla ES5 any more. They'll target something like the most recent two versions of the evergreen browsers and any specific minimum versions of other browsers they need for their particular market. This produces more efficient production code because all major browsers now support much more recent JS natively.

There are also some modern JS APIs that you can't completely polyfill. You have to target a runtime environment that provides real support for those.

Semver is great when it works, but when your culture is to have absurdly deep trees of nested dependencies with hundreds or even thousands of indirect packages involved, things still break often enough to notice.

Major libraries might provide automatic codemods for straightforward, unambiguous changes. However, sometimes you can't divine the original developer intent automatically. Then some manual intervention is required.

I'm interested whether there are any programming language ecosystems that have done this better? As far as I can see Python 2 to 3 caused hard rewrites, etc.

Almost all of them, in my experience. JS, including the ecosystem and culture around it, has by far the worst stability story of any major language I have used.

This is partly a cultural problem. Writing code to last simply isn't part of the mindset or skill set of many people working in web development.

Many tools and libraries we rely on for the most vital functionality are FOSS with at most a small team working on them or maybe just one single person. That means even really successful and widely used projects can easily fade away as those behind them lose interest.

Much of what is built on top is written by people being paid astronomical amounts of money who will job hop in less than two years for even greater astronomical amounts of money. They might make it to senior/staff levels a few years into their careers or maybe become the CTO at a startup, never having either built a new product from scratch or maintained one for 5+ years to see where those decisions they made earlier on come back to haunt them. Then those people are the ones leading and mentoring the next generation of newbies working in the JS community, and the cycle continues.

It's also partly a technical problem. The language doesn't provide much to help with building large-scale software and maintaining it over the long term. What it does provide is relatively recent. The tooling is relatively weak, well behind the state of the art for many other popular languages, which in turn lag the more research-focussed languages where radically different ideas get explored.

I believe a big factor in these cultural and technical problems is the way that you can just change your code and push out a new version any time you want since you have complete control over the servers hosting it. It has also become the norm to depend on online APIs provided by other parties who can do the same. This means concepts like managed releases and support lifetimes and stable interfaces are given less importance.

In striking contrast to all of that, there is code I worked on professionally a couple of decades ago that was written in C and would still compile and run on any modern platform with few or no changes. Likewise, there are professionally developed libraries in ecosystems like Java and .Net, which are platforms widely used for large-scale enterprise software development, that have been around for a decade or more and are still as active as ever. Even in Python, the 2-to-3 shift took place over about a decade, taking the community and the tools and libraries along with it. The language is still mostly compatible with Python 2 code, and there were tools to mechanically update code for most of the main breaking changes, so many of the popular libraries from the Python 2 era are still available and working fine with Python 3.

The only other language I've used where instability was as awful as JS world is Haskell, and that's obviously not a mainstream language in the same sense. It's mostly used by a community who are very open to trying big new ideas and changing how they work frequently, and that's part of its attraction to those people and also probably a reason that ideas from Haskell sometimes drift into more popular use over time but the language itself remains an eccentric choice for production use.

  > The point is that there is a difference between having
  > two APIs that both still work and having one stable API.
This is the direct effect of high levels of backwards compatability. You can't change APIs; you have to create new APIs and then deprecate previous APIs. That's the only way of avoiding a breaking change (other than never changing something and endlessly layering leaky abstractions on top of it).

  > Having multiple integrations with different APIs or
  > different libraries to do the same job is a form of 
  > technical debt, and sometimes it can become quite 
  > expensive.
I disagree. If you don't need to do any work to something it has zero cost. Write tests to its behavior and it can be a blackbox to your team until you truly need to deal with it.

  > A lot of modern build processes don't just target
  > vanilla ES5 any more. They'll target something like 
  > the most recent two versions of the evergreen browsers
  > and any specific minimum versions of other browsers
  > they need for their particular market.
This isn't mainstream yet. Until very recently the majority of companies were targetting IE 11. A lot of companies changed this in 2020 (Microsoft, Atlassian, etc), and additionally due to Node finally supporting ESM and the release of Snowpack and Vite, many open-source developers are finally targetting something greater than ES5. But you're wrong to imply that it's the norm.

  > There are also some modern JS APIs that you can't completely polyfill.
People tended not to use these due to needing to support older browsers. But sometimes APIs could be partially polyfilled to an extent that was sufficient enough to use them (like `Proxy` with `proxy-polyfill`).

  > Almost all of them, in my experience. JS, including the ecosystem and 
  > culture around it, has by far the worst stability story of any major language
  > I have used.
OK, yeah, I'm not seeing this at all. For a start, TC39 has rules against breaking the web (see "One JavaScript", etc: https://tc39wiki.calculist.org/about/faq/). It's due to this choice that we still have mistakes like `typeof null === 'object'`...

Also, I don't think your opinion has wide acceptance within the industry. See comments by Kyle Simpson (https://twitter.com/getify/status/1195362162857910273) or even Yaron Minsky decrying their inability to fix old mistakes (https://twitter.com/yminsky/status/1067926815992410113).

Of course, TC39 is not perfect and there are very rare occasions that minor incompatabilities are introduced (https://tc39.es/ecma262/#sec-additions-and-changes-that-intr...) but "the worst stability story of any major language" is quite an absurd statement if you consider the minutae that has made that list.

  > [...] Much of what is built on top is written by people being paid astronomical amounts 
  > of money who will job hop in less than two years for even greater astronomical amounts
  > of money. 
This is all true. But most of the products these people create are also being replaced every 2 years so it's not as big an issue as you think it is. We're able to go back to projects written in JavaScript 10+ years ago and they work in newer browsers, but the majority of projects are thrown away or rewritten for completely different reasons before this point (normally employee attrition on smaller projects is enough to lose the knowledge required to fix bugs or add features and so companies rewrite to get back that understanding).

I guess a form of backwards compatability we don't have is the ability to upgrade a tooling dependency through multiple breaking changes and not find out that the configuration system has been completely overhauled. That is unfortunate. But the code will build/run when you pull it down the first time from your repository. If you then decide to make upgrades to use new tooling you have to know what you're doing -- tooling upgrades are confusing.

  > The language doesn't provide much to help with building large-scale software and 
  > maintaining it over the long term. What it does provide is relatively recent.
  > The tooling is relatively weak, well behind the state of the art for many other
  > popular languages, which in turn lag the more research-focussed languages where
  > radically different ideas get explored.
I disagree. It has testing frameworks, it has automated code formatters, it has linters, it has type checkers, it has tools to automate rewriting 10,000s of lines of code via the AST, it has tools to automate producing changelogs, it has tools to visualise dependencies, it has tools to improve the performance of scaling a monorepo, etc. Some of these tools are significantly worse in other programming language ecosystems or do not even exist.

  > Even in Python, the 2-to-3 shift took place over about a decade, taking the community
  > and the tools and libraries along with it.
Are you trying to tell me that a breaking change that was so bad that it took almost a decade for the community to complete is something that we should aspire to?

I don't think that JavaScript has serious backwards compatability issues at all. Certainly not in the language. Generally not in the major libraries (React, etc). It perhaps has some issues in breaking changes to the tooling which could make upgrades very confusing (e.g. Babel changed how configuration worked a few times and this was painful due to obscure error messages).

On the other hand, I will say this: it is true that the open-source JavaScript community is high on modularisation, scrappy/innovative and prone to releasing something for fun and then ghosting their consumers. In situations where the quality of the package was high enough that you don't need to change anything this presents no issues, but sometimes when you've used a package with a broad vision that the creator has later on bowed out of fulfilling or which has later on produced lots of bugs, that then leads to engineers swapping it out for newer, shinier or better maintained (for now) things... That is the 'stability' issue that we tend to have issues with and it's the reason that I (and a small minority of other people) have started to 'vendor' or inline code into our projects. As Tom MacWright recently wrote "One of my golden rules is that you shouldn’t blackbox things you don’t need to. I like to “use dependencies for efficiency, not ignorance.”" (quality article by the way: https://macwright.com/2021/03/11/vendor-by-default.html).

This is the direct effect of high levels of backwards compatability. You can't change APIs; you have to create new APIs and then deprecate previous APIs.

I don't see how that follows at all. You can't make breaking changes to APIs, but it's fine to extend them or even expose different levels of abstraction as long as the underlying model you're using stays consistent and you provide suitable defaults where necessary.

If you don't need to do any work to something it has zero cost.

This is tautological, but if we're talking about a typical web application then you are working with that code, every time you make a new build. It might sit there as an untouched black box for a while, but if it has any kind of external dependencies or it relies on anything that could change about the language, platform or other parts of your own code, then there is always a risk that it will later break, and then you'd better hope you have someone around who still knows how to fix it.

This isn't mainstream yet. Until very recently the majority of companies were targetting IE 11.

You've made several claims like that, but in the absence of data there's no way to know whether you're correct. For example, preset-env has been in production for 3+ years now and had an extended beta/RC phase before that. It's true that it defaults to ES5 if you don't configure it, but the Babel docs explicitly recommend that you do, and it is literally a one-line change in your package.json to do something more modern and efficient based on Browserslist unless you genuinely need that degree of backward compatibility.

Of course, in some cases, even quite recently, you did need that. A relatively small proportion of business customers stuck in the IE11 era could still represent significant revenue at risk if you dropped support. But it will take more than an unsupported assertion to convince me that this has been the norm for most web development for quite some time. At one of my businesses, we've had literally no-one using IE11 visit a B2C web app for years. At another that mostly does outsourced development work, we've excluded IE support contractually for a long time and no client of any size has pushed back in years. There must be many thousands of other small businesses out there like mine, and I have to assume that they have senior devs who sometimes read the docs for the tools they use too.

OK, yeah, I'm not seeing this at all.

I think that's because you persist in interpreting my comments as being about JS itself, when I've tried repeatedly to emphasize that it is the culture and surrounding ecosystem that are the bigger problems. I'm not talking about the technical committees defining the language. I'm talking about the developer experience of using it in production.

On that score, I stand by my earlier comments. After many years of programming professionally, using many different languages, I have yet to find any more flaky ecosystem than JavaScript's other than the deliberately fast-paced world of Haskell. Nothing else even comes close for how much wasted effort I've seen over the years just keeping all the plates spinning so nothing falls off and breaks.

But most of the products these people create are also being replaced every 2 years so it's not as big an issue as you think it is.

Yes, I understand the commercial argument. The bizarre economics in the web dev industry sometimes make throwing entire projects out and rewriting every 2 years affordable. That doesn't mean it's not a horribly unstable environment, which was the original point of contention, nor that disregarding traditional wisdom about the dangers of big rewrites isn't a bad idea. It just means parts of the industry are so rich that they can afford to have a toxic culture where quality is a second-class citizen and the only answer to producing so much unmaintainable junk is exactly what you said. It's much nicer working in other parts of the software industry where what you're producing is expected to work and to last, but sadly it doesn't always pay as well.

It has testing frameworks, it has automated code formatters, it has linters...

And these kinds of things are advanced tooling, in your view? We had those in our IDEs for building desktop software back in the last century. Except they were automating rewriting millions of lines of code on 2000-era PCs, not 10,000 lines of code on 2020-era PCs.

I'm not sure what other popular programming language ecosystems you think don't have these kinds of tools today or have tools significantly worse. But in web development, TS is the current hotness because the developers finally realised that explicit typing is helpful for building and maintaining more than small systems, and not so long ago build tools adopting tree shaking was being heralded as a great advance for reducing the size of builds, and before that we got the radical new concept of a module import/export system so you could write code in more than one file without jumping through crazy hoops, and before that we discovered that immediate mode UIs and declarative specs are a thing. All of these ideas were well known and widely used elsewhere in the programming world much, much earlier.

Are you trying to tell me that a breaking change that was so bad that it took almost a decade for the community to complete is something that we should aspire to?

It took that long because that backward compatibility and stability we've been talking about meant a lot of older projects didn't need to move any sooner. And yes, having a platform where you can write code and it keeps working and the ecosystem still positively supports it for another decade is definitely something we should aspire to.

Generally not in the major libraries (React, etc).

Don't tell that to anyone who uses React Router. Or who builds their app with Webpack. Or Babel, as you mentioned. And again, it's important to note that you only said backward compatibility here. If we're talking about the broader concept of stability then you also have to include high profile libraries like Moment giving way to more modern alternatives because although they still work, they don't lend themselves to modern programming styles or play so nicely with other tools.

These comments are getting long and I suspect we may have to agree to disagree on some of this, but if you haven't worked much on software in other parts of the industry, I encourage you to look at what is considered the norm and acceptable practice in fields where better quality and greater longevity are more highly valued. If we built security libraries or the embedded software controlling industrial machinery the way a lot of online companies build their web apps, we'd be lucky to survive the night.