5 ms·
I think AI-assisted programming may be having the opposite effect, at least for me. I'm now incentivized to use less abstractions. Why do we code with React?
by simonw 11mo ago
I think AI-assisted programming may be having the opposite effect, at least for me.
I'm now incentivized to use less abstractions.
Why do we code with React? It's because synchronizing state between a UI and a data model is difficult and it's easy to make mistakes, so it's worth paying the React complexity/page-weight tax in order for a "better developer experience" that allows us to build working, reliable software with less typing of code into a text editor.
If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all.
How often have you dropped in a big complex library like Moment.js just because you needed to convert a time from one format to another, and it would take too long to hand-write that one feature (and add tests for it to make sure it's robust)? With an LLM that's a single prompt and a couple of minutes of wait.
Using LLMs to build black box abstraction layers is a choice. We can choose to have them build LESS abstraction layers for us instead.
- tyre 11mo agoFor moment you an use `date-fns` and tree shake. I'd rather have LLMs build on top of proven, battle-tested production libraries than keep writing their own from scratch. You're going to fill up context with all of its re-invented wheels when it already knows how to use common options. Not to mention that testing things like this is hard. And why waste time (and context and complexity) for humans and LLMs trying to do something hard like state syncing when you can focus on something else?
- simonw 11mo agoEvery dependency carries a cost. You are effectively outsourcing part of the future maintenance of your project to an external team. This can often be a very solid bet, but it can also occasionally backfire if the library you chose falls out of date and is no longer maintained. For this reason I lean towards fewer dependencies, and have a high bar for when a dependency is worth adding to a project. I prefer a dozen well vetted dependencies to hundreds of smaller ones that each solve a problem that I could have solved effectively without them.
- tyre 11mo agoFor smol things like left-pad, sure but the two examples given (moment and react) solve really hard problems. If I were reviewing a PR where someone tried to re-implement time zone handling in JS, that’s not making it through review. In JS, the DOM and time zones are some of the most messed up foundations you’re building on top of ime. (The DOM is amazing for documents but not designed for web apps.) I think we really need to be careful about adding dependencies that we’re maintaining ourselves, especially when you factor in employee churn and existing options. Unless it’s the differentiator for the business you’re building, my advice to engineers is to strongly consider other options and have a case for why they don’t fit. AI can play into the engineering blind spot of building it ourselves because it’s fun. But engineering as a discipline requires restraint.
- simonw 11mo agoWhether that's true about React and Moment varies on a case-by-case basis. If you're building something simple like a contact form React may not be the right choice. If you're building something like Trello that calculation is different. Likewise, I wouldn't want Moment for https://tools.simonwillison.net/california-clock-change https://tools.simonwillison.net/california-clock-change but I might want it for something that needs its more advanced features.
- deleted 11mo ago[deleted]
- azangru 11mo ago> Why do we code with React? ...is a loaded question, with a complex and nuanced answer. Especially when you continue: > it's worth paying the React complexity/page-weight tax All right; then why do we code in React when a smaller alternative, such as Preact, exists, which solves the same problem, but for a much lower page-weight tax? Why do we code in React when a mechanism to synchronize data with tiny UI fragments through signals exists, as exemplified by Solid? Why do people use React to code things where data doesn't even change, or changes so little that to sync it with the UI does not present any challenge whatsoever, such as blogs or landing pages? I don't think the question 'why do we code with React?' has a simple and satisfactory answer anymore. I am sure marketing and educational practices play a large role in it.
- simonw 11mo agoYeah, I share all of those questions. My cynical answer is that most web developers who learned their craftsin the last decade learned frontend React-first, and a lot of them genuinely don't have experience working without it. Which means hiring for a React team is easier. Which means learning React makes you more employable.
- whstl 11mo ago> most web developers who learned their craftsin the last decade learned frontend React-first, and a lot of them genuinely don't have experience working without it That's not cynical, that's the reality. I do a lot of interviews and mentor juniors, and I can 100% confirm that. And funny enough, React-only devs was a bigger problem 5 years ago. Today the problem is developers who can *only* use Next.js. A lot can't use Vite+React or plain React, or whatever. And about 50% of Ruby developers I interviewed from 2022-2024 were unable to code a FizzBuzz in Ruby without launching a whole Rails project.
- CharlieDigital 11mo agoMy test for FE is to write a floating menu in JSFiddle with only JS, CSS, and HTML. Bonus if no JS. If you can do that, then you can probably understand how everything else works.
- sshine 11mo ago> I'm now incentivized to use less abstractions. I'm incentivised to use abstractions that are harder to learn, but execute faster or more safely once compiled. E.g. more Rust, Lean. > If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all. LLMs benefit from abstractions the same way as we do. LLMs currently copy our approaches to solving problems and copy all the problems those approaches bring. Letting LLMs skip all the abstractions is about as likely to succeed as genetic programming is efficient. For example, writing more vanilla JS instead of React, you're just reinventing the necessary abstractions more verbosely and with a higher risk of duplicate code or mismatching abstractions. In a recent interview with Bret Weinstein, a former professor of evolutionary biology, he proposed that one property of evolution that makes the story of one species evolving into another more likely is that it's not just random permutations of single genes; it's also permutations to counter variables encoded as telomeres and possibly microsatellites. https://podcasts.happyscribe.com/the-joe-rogan-experience/2427-bret-weinstein https://podcasts.happyscribe.com/the-joe-rogan-experience/24... Bret compares this to flipping random bits in a program to make it work better vs. tweaking variables randomly in a high-level language. Mutating parameters at a high-level for something that already works is more likely to result in something else that works than mutating parameters at a low level. So I believe LLMs benefit from high abstractions, like us. We just need good ones; and good ones for us might not be the same as good ones for LLMs.
- simonw 11mo ago> For example, writing more vanilla JS instead of React, you're just reinventing the necessary abstractions more verbosely and with a higher risk of duplicate code or mismatching abstractions. Right, but I'm also getting pages that load faster and don't require a build step, making them more convenient to hack on. I'm enjoying that trade-off a lot.
- joquarky 11mo agoVanilla JS is also a lot more capable than it was when React was invented. And yeah, you can't beat the iteration speed. I feel like there are dozens of us.
- starkparker 11mo agoI'd rather use React than a bespoke solution created by an ephemeral agent, and I'd rather self-trepanate than use React
- roadside_picnic 11mo ago> If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all. I've had plenty of junior devs justify massive code bases of random scripts and 100+ line functions with the same logic. There's a reason senior devs almost always push back on this when it's encountered. Everything hinges on that "if". But you're baking a tautology into your reasoning: "if LLMs can do everything we need them to, we can use LLMs for everything we need". The reason we stop junior devs from going down this path is because experience teaches us that things will break and when they do, it will incur a world of pain. So "LLM as abstraction" might be a possible future, but it assumes LLMs are significantly more capable than a junior dev at managing a growing mess of complex code. This is clearly not the case with simplistic LLM usage today. "Ah! But you need agents and memory and context management, etc!" But all of these are abstractions. This is what I believe the parent comment is really pointing out. If AI could do what we originally hoped it could: follow simple instructions to solve complex tasks. We'd be great, and I would agree with your argument. But we are very clearly not in that world. Especially since Karpathy can't even keep up with the sophisticated machinery necessary to properly orchestrate these tools. All of the people decrying "you're not doing it right!" are emphatically proving that LLMs cannot perform these tasks at the level we need them to.
- mannanj 11mo ago> things will break and when they do, it will incur a world of pain How much if this is still true and exaggerated in our world environment today where the cost of making things is near 0? I think “Evolution” would say that the cost of producing is near 0 so the possibility of creating what we want is high. The cost of trying again is low so mistakes and pain aren’t super high. For really high stakes situation (which most situations are not) bring the expert human in the loop until the expert better than that human is AI.
- neoromantique 11mo agoI'm sorry, but I don't agree. Current dependency hell that is modern development, just how wide the openings are for supply chain attacks and seemingly every other week we get a new RCE. I'd rather 100 loosely coupled scripts peer reviewed by a half a dozen of LLM agents.
- nzoschke 11mo agoRight there with you. I'm instructing my agents to doing old school boring form POST, SSR templates, and vanilla JS / CSS. I previously shifted away from this to abstractions because typing all the boilerplate was tedious. But now that I'm not typing, the tedious but simple approach is great for the agent writing the code, and great for the the people doing code reviews.
- jayd16 11mo agoWhy would I want to maintain in perpetuity random snippets when a library exists? How is that an improvement?
- oulipo2 11mo agoThat's a fundamental misunderstanding The role of abstractions *IS* to prevent (eg "compress") the need for a test suite, because you have an easy model to understand and reason about
- simonw 11mo agoOne of my personal rules for automated test suites is that my tests should fail if one of the libraries I'm using changes in a way that breaks my features. Makes upgrading dependencies so much less painful!
- oulipo2 11mo agoOf course, but this is largely unmaintainable, shifting the responsibility of correctness check from libraries to users. That's why we modularize/abstract/simplify, in order to minimize the need for actual checks
- casualscience 11mo agoIf you work at a megacorp right now, you know whats happening isn't people deciding to use less libraries. It's developers being measured by their lines of code, and the more AI you use the more lines of code and 'features' you can ship. However, the quality of this code is fucking terrible, no one is reading what they push deeply, and these models don't have enough 'sense' to make really robust and effective test suites. Even if they did, a comprehensive test suite is not the solution to poorly designed code, it's a band aid -- and an expensive one at scale. Most likely we will see some disasters happening in the next few years due to this mode of software development, and only then will people understand to use these agents as tools and not replacements. ...Or maybe we'll get AGI and it will fix/maintain the trash going out there today.
- akoboldfrying 11mo ago> and it can maintain a test suite that shows everything works correctly Are you able to efficiently verify that the test suite is testing what it should be testing? (I would not count "manually reviewing all the test code" as efficient if you have a similar amount of test code to actual code.) Sometimes a change to the code under test means that a (perhaps unavoidably brittle) test needs to be changed. In this case, the LLM should change the test to match the behaviour of the code under test. Other times, a change to the code under test represents a bug that a failing test should catch -- in this case, the LLM should fix the code under test, and leave the test unchanged. How do you have confidence that the LLM chooses the right path in each case?
- travisgriggs 11mo agoHas anyone tried the experiment that is sort of implied here? I was wondering earlier today, what it would be like to pick a simple app, pick on OS, and just tell an LLM to write that app using only machine code and native ADKs, and skip all intermediate layers? We seem to have created a large bureaucracy for software development, where telling a computer how to execute an app involves keeping a lot of cogs in a big complicated machine happy. But why use the automation to just roll the cogs? Why not just simplify/streamline? Does an LLM need to worry about using the latest and greatest abstractions? I have to assume this has been tried already...
- nkrisc 11mo agoIf LLMs are that capable, then why are AI companies selling access to them instead of using them to conquer markets?
- lithocarpus 11mo agoI would guess fear of losing market share and valuable data, as well as pressure to appear to be winning the AI race for the companies' own stock price. i.e competition. If there were only one AI company, they would probably not release anything close to their most capable version to the public. ala Google pre-chatgpt.
- tjr 11mo agoI’m not sure that really answers the question? Or perhaps my interpretation of the question is different. If (say) the code generation technology of Anthropic is so good, why be in the business of selling access to AI systems? Why not instead conquer every other software industry overnight? Have Claude churn out the best office application suite ever. Have Claude make the best operating system ever. Have Claude make the best photo editing software, music production software, 3D rendering software, DNA analysis software, banking software, etc. Why be merely the best AI software company when you can be the best at all software everywhere for all time?
- sod22 11mo agoIm waiting for people to realise that software products are much more than just lines of code. Getting sick and tired of people talk about their productivity gains when not much is actually happening out there in terms of real value creation.
- pertymcpert 11mo agoJust because you don't see it or refuse to believe people doesn't make you right and them liars. Maybe you're just wrong.
- rdhatt 11mo agoI find it interesting for your example you chose Moment.js -- a time library instead of something utilitarian like Lodash. For years I've following Jon Skeet's blog about implementing his time library NodaTime (a port of JodaTime). There are a crazy number of edge cases and many unintuitive things about modeling time within a computer. If I just wanted the equivalent of Lodash's _.intersection() method, I get it. The requirements are pretty straightforward and I can verify the LLM code & tests myself. One less dependency is great. But with time, I know I don't know enough to verify the LLM's output. Similar to encryption libraries, it's a common recommendation to leave time-based code to developers who live and breathe those black boxes. I trust the community verify the correctness of those concepts, something I can't do myself with LLM output.
- cyberax 11mo agoThe problem is, what do you do _when_ it fails? Not "if", but "when". Can you manually wade through thousands of functions and fix the issue?
- losvedir 11mo agoHuh, I've been assuming the opposite: better to use React even if you don't need it, because of its prevalence in the training data. Is it not the case that LLMs are better at standard stacks like that than custom JS?
- simonw 11mo agoHard to say for sure. I've been finding that frontier LLMs write very good code when I tell them "vanilla JS, no React" - in that their code matches my personal taste at least - but that's hardly a robust benchmark.
- api 11mo agoNutty idea: train on ASM code. Create an LLM that compiles prompts directly to machine code.
- majormajor 11mo ago> If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all. for simple stuff, sure, React was ALWAYS inefficient. Even Javascript/client-side logic is still overkill a lot of the times except for that pesky "user expectations" thing. for anything codebase that's long-lived and complex, combinatorics tells us how it'll near-impossible to have good+fast test coverage on all that. part of the reason people don't roll their own is because being able to assume that the library won't have major bugs leads to an incredible reduction in necessary test service, and generally people have found it a safe-enough assumption. throwing that out and trying to just cover the necessary stuff instead - because you're also throwing out your ability to quickly recognize risky changes since you aren't familiar with all the code - has a high chance of painting you into messy corners. "just hire a thousand low-skilled people and force them to write tests" had more problems as a hiring plan then just "people are expensive."
- godelski 11mo ago> I'm now incentivized to use less abstractions. I'd argue it's a different category of abstraction
- throwaway150 11mo ago> If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all. But this is a highly non-trivial problem. How do you even possibly manually verify that the test suite is complete and tests all possible corner cases (of which there are so many because synchronizing state is a hard problem)? At least React solves this problem in a non-stochastic, deterministic manner. What can be a good reason to replace something like React that works determinstically with LLM-assisted code that is generated stochastically and there's no easy way to manually verify if the implementation or the test suite is correct and complete?
- mlinhares 11mo agoYou don't, same as for the "generate momentjs and use it". People now firmly believe they can use an LLM to build custom versions of these libraries and rewrite whole ecosystems out of nowhere because Claude said "here's the code". I've come to realize fighting this is useless, people will do this, its going to create large fuck ups and there will be heaps of money to be made on the cleanup jobs.
- pertymcpert 11mo agoThere's going to be lots of fuck ups, but with frontier models improving so much there's also going to be lots of great things made. Horrible, soul crushing technical debt addressed because it was offloaded to models rather than spending a person's thought and sanity on it. I think overall for engineering this is going to be a net positive.
- bonesss 11mo agoI think the gap between people dealing with JavaScript cruft all day and backend large systems development is creating a massive conversational disconnect… like, this thread is plain-faced and seriously discussing reinventing date handling locally for funsies. I also think that any company creating a reverse-centaur workforce of blind and dumb half baked devs ritualistically shaking chicken bones at their pay-as-you-go automaton has effectively outsourced their core business to OpenAI/MS while paying for the privilege. And, on the twenty year timeline as service and capital costs create crunches, those mega corps will literally be sitting on whole copies of internal business schematics and critical code of their subservient customers… They say things, they do other things. Trusting Microsoft not to eat your sector through abusive partner programs and licensing entanglements backed with government capture? Surely the LLMs can explain how that has gone historically and how smart that is going forward.
- avaika 11mo agoI don't trust LLM enough to handle the maintenance of all the abstraction buried in react / similar library. I caught some of the LLMs taking nasty shortcuts (e.g. removing test constraints or validations in order to make the test green). Multiple times. Which completely breaks trust. And if I have to closely supervise every single change, I don't believe my development process will be any better. If not worse. Let alone new engineers who join the team and all of a sudden have to deal with a unique solution layer which doesn't exist anywhere else.
- qingcharles 11mo agoLLMs also have encyclopedic knowledge. Several times LLMs have found some huge block of code I wrote and reduced it down to a few lines. The other day they removed several thousand lines of brittle code I wrote previously for some API calls with a well-tested package I didn't know about. Literally thousands down to dozens. My code is constantly shrinking, becoming better quality, more performant, more best-practice on a daily basis. And I'm learning like crazy. I'm constantly looking up changes it recommends to see why and what the reasons are behind them. It can be a big damned dummy too, though. Just today it was proposing a massive server-side script to workaround an issue with my app I was deploying, when the actual solution was to just make a simple one-line change to the app. ("You're absolutely right!")
- briandw 11mo agoI've come to a similar conclusion. One example is how much easier it is to put an interface on top of sqlite. I've been burned badly with the hidden details of ORM s. ORMs are the sirens call of getting rid of all that boiler plate code when encoding and decoding objects into a db. However this abstraction breaks in many hidden ways. Lazy loading details, in-memory state vs db mismatch, cascading details, etc all have unexpected problems that can be hard to predict. Using an LLM to do the grunt work lets you easily see and reason about all the details. You don't have to guess about what's happening and you can make your own choices.
- fweimer 11mo ago> If an LLM is typing that code - and it can maintain a test suite that shows everything works correctly - maybe we don't need that abstraction after all. I'm worried that there is a tendency in LLM-generated code to avoid even local abstractions, such as putting common code into separate (local functions), and even use records/structures. You end up with code that is best maintained with an LLM, which is good for the LLM provider and their future revenue. But we humans as reviewers and ultimate long-term maintainers benefit from those minor abstractions.
- simonw 11mo agoYeah, I find myself needing to watch out for that. I'll frequently say "refactor that to reduce duplicated code" - which is generally very safe once the LLM has added test coverage for the new feature.