The Tower Keeps Rising
lucumr.pocoo.org547 points by cdrnsf 2 days ago
547 points by cdrnsf 2 days ago
I've said for a long time that composability in software is a bit like playing Tetris: the lines have to clear.
I feel like that gives an even more literal tower-rising metaphor, and that's what it feels like people using agents naively (and software engineers of lower skill or earlier-career), end up violating.
Agents are getting better at folding things into themselves, especially if you direct them to... but unfortunately I've found that the architectural instincts, even of Fable and 5.6 Sol, are still wildly behind what I reflexively achieve, say.
For sure there is an ability to have agents go back over work and try to fold it into better and better abstractions until it's sort of annealed into something good. I've done something similar on codebases that I have, but the 'high reaches' of architecture with great _prediction of how the software will evolve in the future_ in _subtle_ ways – those are, for now, out of reach of agents.
There is a part of me that wonders if it's partly just how much they can hold in their head right now, though. Even with the greatest articulation and high density of feeding them, the current setups don't allow them to hold a high-quality, sparse, 'zoomable' model of the world in their head that well yet, which we can do pretty well.
But the fact that I'm talking about it in terms of that kind of subtlety is itself promising, I guess?
The upper bound on program complexity used to be the power of the human mind. "Vibe coding" can break through that barrier. But not because the problem being solved needs that complexity. Because the process does not drive itself towards compact abstractions. It's the AI-powered version of the scaling problem Brooks described back in "The Mythical Man-Month". The combinatoric problems get worse with scale. Concretely, multiple similar implementations of roughly the same thing appear in different parts of the project. This is a known problem of vibe coding now.
We need some way to make AI-driven coding strive for parsimony.
Why would it? It has optimized what it was built to optimize: this is the token-selling industry. Take note that the people hawking the dream of a gold rush are not actually mining but selling shovels
Same issue happens in models trained by organizations who aren’t selling tokens. I believe it’s because being parsimonious is simply harder. Achieving the task at hand independently and declaring the job done is easier than building an abstraction and reconciling between every use case.
Agreed. I've noticed this happens without fail in any project driven primarily by "tickets" and "sprints". Finishing the immediate task ends up taking precedence over future concerns that cover a wider scope. On the other end of the spectrum it's easy to spend too much time at the beginning humming and hawing about the best, most future proof design, because you just know you're not going to be able to easily fix it later. As is often the case, the right approach is somewhere inbetween, which is partly why it's a hard process to automate. you're constantly making judgement calls.
I have a vaguely-relevant war story.
1998 - Huge business, re-writing some vital piece of the platform in the middle of Y2K. Contract coders are expensive but also the only available people to throw at this.
The architect had mapped out the entire system down to class/method level. They'd produced a huge list of classes and methods that needed to be built. So the company hired a bunch of contract coders to build said classes and methods, including your humble protagonist. We were each given a list of methods to write up - parameters, operation, expected output. We wrote them up, and ticked them off the list. We were not briefed on how they interacted. There were no tests that we could run. There was apparently no-one checking that what we wrote in the method actually matched the spec. This was before git, so version control was extremely rough, and also before JIRA (iirc the list was an Access database).
We all realised very quickly, like the first week, that this entire project was doomed. But we were getting paid a lot of money to do this, so we just did it. It got really boring really quickly. Every day we wrote a bunch of methods, and next day got a list of the next set of methods to write. The lists just kept coming, with no idea how long the master list was, or how the classes interacted with each other, or how the system actually worked, or anything.
I left after a month. The money was good, but the boredom was driving me insane.
I learned later from friends who stayed that the whole project was canned a couple of months later when it became obvious that this was a complete waste of money and would never work.
Whenever I see a project manager staring at JIRA instead of talking to their people or looking at the codebase, I'm reminded of this project. And your comment reminded me of that ;)
Crazy to think that if it was specced out so well, a modern LLM would make short work of the whole thing. The things we used to get paid for!
lolol you're joking right? as a joke it's funny. If you think thats really what it sounds like when a project's design is well-understood... ... ...
Labs are trying to make long-horizon work. Even if you're a coding agent, adding more and more surface area is distracting to that goal. There is reason that RL over long traces should, at least in principle, optimize for building in ways that help the result fit in the model's context window.
A meaningful risk of course is that the tools available to the model (ripgrep + fancier semantic approaches) allow it to do a good job of reasoning over things much larger than its context window, and so it doesn't pay the penalty sufficiently to fix it.
Does that not sound a little silly to you when you say it? Should I invest in becoming a memory athlete as a way of becoming a better software engineer? ...or should I learn how to build and use tools?
While I don't disagree, memory certainly was more of a restrictions on us humans than it is on llms. Therefore, the answer may not be as obvious as it seems. We build abstractions to reduce (memory) footprint of features, right?
Humans built codebases many millions of lines long, well before LLMs existed. Human memory has not been a restriction on us in a long time.
Look at all the libraries full of books we've built. It's useful for more than mere training sets.
I think the trick here is plural; I guarantee no single human knows all 1 million lines. Note this is different than knowing how to orient yourself in a million line codebase quickly.
The limit here I think the ancestor comments are getting at is cognitive load, which is real and measured. We only have so much memory to devote to a "stack" when executing, and it's usually quite constrained.
Note this is different than knowing how to orient yourself in a million line codebase quickly.
Hence my library mention. Humans have been doing this for millennia: orienting ourselves within a library (the physical kind, full of books) and calling upon its information resources as needed to accomplish tasks (research). Ultimately, it's all just one big cache hierarchy. Your short term memory, your long term memory, the book in your hands, the desk at the library, the nearby shelves, the card catalogue, the stacks, the inter-library loan system.
To manage it all, we humans have developed our abilities for abstraction. When we build clean, tight abstractions we reduce our cognitive load. Perhaps the best abstraction we've built so far is the TCP/IP and web stack. We don't need to care at all about the hardware details of a server in order to talk to it. It's such a powerful and airtight abstraction that we take it for granted.
I'd like to hear from more people who have spent a lot of time building with LLMs, because so far what people are saying is that these models do not have the ability to reason about and build the kind of marvellous abstractions us humans have built.