It’s good to read an article that carefully balances good and bad points, dreams and practicality, instead of just advocating for whatever the author is currently into or slagging what they’ve dumped.
Very much an article about ‘how this regretted outcome came to be’. Some key paragraphs:
A couple of teams, our most enthusiastic, early adopters of Elm, completed their migration away from React. Having worked hard to embrace Elm’s nirvana of type-safe, pure functional programming, the last thing those teams wanted to do was break out their increasingly rusty React skills whenever they contributed a change to a design system component.
[…]
It seemed we were faced with a choice: Elm or React. Continuing to support both was fast becoming unsustainable for us.
The thing that ultimately tipped the balance in React’s favour for us was that we acquired another company whose entire codebase was written in React, and whose team knew nothing about Elm. Overnight, we went from a company that was writing about equal amounts of Elm and React (and which might well have decided to double down on Elm) to one that was writing about 75% React.
[…]
Elm is really designed to be your whole front end stack. We have gotten around this fact by investing in tools (i.e. super cool hacks) which allow Elm to integrate with our blended stack. But there are some consequences to using Elm in this way: […] we don’t get to use Elm as our single dependency — it is actually just one more (big) piece of complexity for the rest of our tools and code to consider. This means that we don’t see the benefits of Elm either as a low-maintenance front end stack, nor as a way to guarantee consistent low-cost context switching.
[…]
we believe that choosing a single language and framework (React) for new projects is the best path for Culture Amp, as it will buy us economies of scale within the front end practice.
Seems to me like a pretty decent example of why “Pinky & The Brain” systems seldom go anywhere. ;_;
My takeaway was more like “React is why we can’t have nice things” which … I kind of already knew was true.
Extremely depressing but at the end of the day having better technology can’t overcome the enormous momentum of an industry that has enthusiastically embraced a mediocre alternative.
… which in fairness isn’t exactly React’s fault; convergence on mediocrity (a.k.a. “best practices”) is an ongoing challenge in many industries.
You want to have a defined minimum bar, but that’s almost certainly going to be a low bar.
So then many pressures - the ability to hire quickly (including to easily assess candidates) and at scale, ability to treat engineering staff as fungible, ability to pay other people to solve your problems (or even look them up on StackExchange) - all come to bear.
Some for better, some for worse, but you wind up with your industry’s equivalent of React. C.f. Java, or dietary guidance for children that’s a decade behind the science.
Java’s old, but it’s anything but mediocre. Tastes vary; I get that. But it has been a high quality project for decades, and if they weren’t in such a rush to begin with (when Microsoft was trying to destroy Java), it would probably have way less tech debt (e.g. the bloated and super-complicated Taligent stuff that IBM donated, and lots of other “core” libraries like crypto that show every sign of having been rushed).
I came from the C++ world, which had dramatically worse tool-chains, dramatically worse (or usually, just missing) libraries, and where a programming mistake was fatal (at least to the program). At the time, there were widely used “high level” languages like Perl, PHP, Visual Basic, Access, PowerBuilder, Gupta, DBase, FoxPro, Excel…. So in comparison, Java was shockingly better than the alternatives.
And with Guy Steele involved, it started with a solid language spec and runtime spec. Almost unheard of back then.
There’s nothing wrong with not liking a language, but Java is anything but mediocre.
if they weren’t in such a rush to begin with (when Microsoft was trying to destroy Java), it would probably have way less tech debt
We’re talking about the Java that actually exists, not a hypothetical possible Java which might have been.
Yeah, sure it’s better than C++ and PHP and VB, but we’re talking about a language that took decades to add something as fundamental as first-class functions. Even in the mid-90s when Java came out, closures weren’t exactly a cutting edge new technology.
Just because it’s better than the three worst languages I can think of doesn’t mean it’s not mediocre.
Yeah, I find that when “worse is better” is invoked to retroactively justify the dominance of POSIX and C, the prevalent emotional response (including my own, guilty as charged) is positive. “Yeah! Worse is better! All that other stuff was so overengineered! Thank goodness for worse-is-better or we’d be stuck with MULTICS and ADA”
But looking at all the “worse is better” situations playing out now, I can’t help, like you, feeling a bit depressed about all the beauty and elegance that is being trampled underfoot by giants (such as React, Javascript, Kubernetes, etc). Perhaps the better-is-better technologists of the past felt the same? Lispers have the unique privilege of having been on the side of better-is-better for several decades now, constantly being sidelined by pareto-sufficient copies of lispy technologies.
I feel this says something about survivorship bias, 20:20 hindsight, etc.
Around this same time the momentum around Elm’s own development and that of its tooling was losing steam.
…
Culture Amp is a medium-sized tech company that can afford to contribute back to the open source ecosystem it depends upon, but in Elm’s case it was beginning to feel like we would have to contribute more than we would get back to make it work well for us.
The breaking changes of Elm 0.18 → 0.19 were not unreasonable, and yet it took a small group of volunteers across multiple teams about a year to do it… When no one is finding the time and motivation to keep a technology healthy in your stack, you can infer how people feel about it.
And the people on the front line were feeling the same about the cost/benefit analysis:
I let these engineers know that I was thinking about moving Elm from “adopt” to “contain”, I asked them what they thought, and I listened.
Every single one of them said they understood and agreed with the decision.
I’m not at all an Elm fan, but I think it actually did. It wasn’t sustainable long-term but the short-term and medium-term benefits were enough for them to get products launched and the business made apparently sustainable. I agree with Kevin (the author)’s assertion that:
Just because a relationship ends doesn’t make it a failure.
Seems to me like a pretty decent example of why “Pinky & The Brain” systems seldom go anywhere. ;_;
I disagree with that characterisation. It’s obvious that Elm isn’t a good fit for all environments, but there are still plenty out there where the self-contained ecosystem is an advantage. Whether or not that’s enough to keep the project going is another question though.
As a counterpoint, it seems like most successful languages have a smooth on-ramp for integration into existing code bases and ecosystems, of which the latter include type systems these days.
After reading it, I think this article contains a pretty good blueprint for how to deprecate important pervasive pieces of technology at a medium-sized organisation.
Elm seems optimal for a very specific niche: small-to-medium sized components (or smaller SPAs) where you’re using relatively few external JS libraries and are able to let its view of the world dominate. Model/view/update seems to struggle to scale up to larger applications, as you spend code routing messages up and down your modules (I vividly recall someone at a conference describing this as “bureaucrats whose only job is stamping papers”). Functional Reactive Programming (FRP) does fix this, but has a very steep learning curve. (In exchange, you get composable, completely consistent UIs, with proper atomic updates. It’s extremely cool.)
Elm’s decision to limit the type system to avoid Haskellesque galaxybraining was probably good for getting a lot of JS developers on board, but I think allowed TypeScript to steal some of its thunder in recent years. Which is a shame, because I consider FP (and especially strongly statically-typed pure ML-style FP) to be an extremely intuitive paradigm for solving real-world problems. It’ll be interesting to see how Elm goes in the future. We use it at $WORK, and because it can control pretty much everything and we have a Haskell backend, it’s been a great fit for us.
Culture Amp’s engineering leadership maintains an internal “Tech Radar” that lists technologies in four categories: “adopt”, “experiment”, “contain”, and “hold.”
Reminds me that we have making a tech radar on our list of things to do…. There’s a lot of things I would like to put in that”contain” category
In TypeScript getting better in a lot axes, becoming the de-facto web language and JS dev becoming increasingly large-framework centric sucked all the air out of alt-js language space. All the SaaS SDKs and frameworks with generated types are TypeScript-first. We’ll see this trend of dropping alt-js languages more and more, because of how the JS ecosystem grew over the last few years. You can’t get away with writing a few bindings and using mostly bespoke code and stay competitive.
I think we need a new generation of languages that play well with TypeScript type system and let you import TS and JS without writing bindings. Think @cImport of Zig.
Surprised that there was no mention of that here, maybe it flew under the radar? Personally I feel it would have fit perfectly with the paradigm of seamlessly integrating with React components. ReScript’s mission is to layer a strong and sound type system on top of JavaScript while compiling to almost exactly the same JavaScript that ‘traditional’ React toolchains would. To users of the components there would be no discernible difference.
It’s ironic that they were so heavily into Elm that they ended up fully losing the benefits of an ML-family language.
It’s good to read an article that carefully balances good and bad points, dreams and practicality, instead of just advocating for whatever the author is currently into or slagging what they’ve dumped.
Very much an article about ‘how this regretted outcome came to be’. Some key paragraphs:
[…]
[…]
[…]
So basically, “the benefits of using Elm didn’t weigh enough against the costs of integrating Elm with other systems”?
Seems to me like a pretty decent example of why “Pinky & The Brain” systems seldom go anywhere. ;_;
My takeaway was more like “React is why we can’t have nice things” which … I kind of already knew was true.
Extremely depressing but at the end of the day having better technology can’t overcome the enormous momentum of an industry that has enthusiastically embraced a mediocre alternative.
… which in fairness isn’t exactly React’s fault; convergence on mediocrity (a.k.a. “best practices”) is an ongoing challenge in many industries.
You want to have a defined minimum bar, but that’s almost certainly going to be a low bar.
So then many pressures - the ability to hire quickly (including to easily assess candidates) and at scale, ability to treat engineering staff as fungible, ability to pay other people to solve your problems (or even look them up on StackExchange) - all come to bear.
Some for better, some for worse, but you wind up with your industry’s equivalent of React. C.f. Java, or dietary guidance for children that’s a decade behind the science.
C.f. Java
Java’s old, but it’s anything but mediocre. Tastes vary; I get that. But it has been a high quality project for decades, and if they weren’t in such a rush to begin with (when Microsoft was trying to destroy Java), it would probably have way less tech debt (e.g. the bloated and super-complicated Taligent stuff that IBM donated, and lots of other “core” libraries like crypto that show every sign of having been rushed).
I came from the C++ world, which had dramatically worse tool-chains, dramatically worse (or usually, just missing) libraries, and where a programming mistake was fatal (at least to the program). At the time, there were widely used “high level” languages like Perl, PHP, Visual Basic, Access, PowerBuilder, Gupta, DBase, FoxPro, Excel…. So in comparison, Java was shockingly better than the alternatives.
And with Guy Steele involved, it started with a solid language spec and runtime spec. Almost unheard of back then.
There’s nothing wrong with not liking a language, but Java is anything but mediocre.
This feels a lot like damning with faint praise.
We’re talking about the Java that actually exists, not a hypothetical possible Java which might have been.
Yeah, sure it’s better than C++ and PHP and VB, but we’re talking about a language that took decades to add something as fundamental as first-class functions. Even in the mid-90s when Java came out, closures weren’t exactly a cutting edge new technology.
Just because it’s better than the three worst languages I can think of doesn’t mean it’s not mediocre.
OK.
That doesn’t make a language mediocre.
I’m interested in what was the “better” to Java’s “worse”, at the time Java was being pushed into popularity by Sun.
Yeah, I find that when “worse is better” is invoked to retroactively justify the dominance of POSIX and C, the prevalent emotional response (including my own, guilty as charged) is positive. “Yeah! Worse is better! All that other stuff was so overengineered! Thank goodness for worse-is-better or we’d be stuck with MULTICS and ADA”
But looking at all the “worse is better” situations playing out now, I can’t help, like you, feeling a bit depressed about all the beauty and elegance that is being trampled underfoot by giants (such as React, Javascript, Kubernetes, etc). Perhaps the better-is-better technologists of the past felt the same? Lispers have the unique privilege of having been on the side of better-is-better for several decades now, constantly being sidelined by pareto-sufficient copies of lispy technologies.
I feel this says something about survivorship bias, 20:20 hindsight, etc.
(*updated for typo)
Kubernetes itself is amazingly engineered.
It’s the problems that it’s trying to solve (a giant legacy layer cake of entropy) that we should all be embarrassed by 🤣
(Although you probably were talking about all of the new layers of the cake that sprouted up on top of Kubernetes. Yeah, agreed on that.)
Ah, there’s a few other nuances:
And the people on the front line were feeling the same about the cost/benefit analysis:
I really appreciated that the author did one-on-ones with all the ICs about it.
I’m not at all an Elm fan, but I think it actually did. It wasn’t sustainable long-term but the short-term and medium-term benefits were enough for them to get products launched and the business made apparently sustainable. I agree with Kevin (the author)’s assertion that:
I disagree with that characterisation. It’s obvious that Elm isn’t a good fit for all environments, but there are still plenty out there where the self-contained ecosystem is an advantage. Whether or not that’s enough to keep the project going is another question though.
As a counterpoint, it seems like most successful languages have a smooth on-ramp for integration into existing code bases and ecosystems, of which the latter include type systems these days.
After reading it, I think this article contains a pretty good blueprint for how to deprecate important pervasive pieces of technology at a medium-sized organisation.
Elm seems optimal for a very specific niche: small-to-medium sized components (or smaller SPAs) where you’re using relatively few external JS libraries and are able to let its view of the world dominate. Model/view/update seems to struggle to scale up to larger applications, as you spend code routing messages up and down your modules (I vividly recall someone at a conference describing this as “bureaucrats whose only job is stamping papers”). Functional Reactive Programming (FRP) does fix this, but has a very steep learning curve. (In exchange, you get composable, completely consistent UIs, with proper atomic updates. It’s extremely cool.)
Elm’s decision to limit the type system to avoid Haskellesque galaxybraining was probably good for getting a lot of JS developers on board, but I think allowed TypeScript to steal some of its thunder in recent years. Which is a shame, because I consider FP (and especially strongly statically-typed pure ML-style FP) to be an extremely intuitive paradigm for solving real-world problems. It’ll be interesting to see how Elm goes in the future. We use it at
$WORK
, and because it can control pretty much everything and we have a Haskell backend, it’s been a great fit for us.Reminds me that we have making a tech radar on our list of things to do…. There’s a lot of things I would like to put in that”contain” category
In TypeScript getting better in a lot axes, becoming the de-facto web language and JS dev becoming increasingly large-framework centric sucked all the air out of alt-js language space. All the SaaS SDKs and frameworks with generated types are TypeScript-first. We’ll see this trend of dropping alt-js languages more and more, because of how the JS ecosystem grew over the last few years. You can’t get away with writing a few bindings and using mostly bespoke code and stay competitive.
I think we need a new generation of languages that play well with TypeScript type system and let you import TS and JS without writing bindings. Think
@cImport
of Zig.Like ReScript? https://rescript-lang.org/docs/gentype/latest/introduction
I had actually been under the impression that Culture Amp had been using ReScript (at the time known as ReasonML): https://www.youtube.com/watch?v=j5mlMUzpE5g&t=56s
Surprised that there was no mention of that here, maybe it flew under the radar? Personally I feel it would have fit perfectly with the paradigm of seamlessly integrating with React components. ReScript’s mission is to layer a strong and sound type system on top of JavaScript while compiling to almost exactly the same JavaScript that ‘traditional’ React toolchains would. To users of the components there would be no discernible difference.
It’s ironic that they were so heavily into Elm that they ended up fully losing the benefits of an ML-family language.