> Maintainability and understandability only show up when you’re deliberate about them. Extracting meaning into well-named functions is how you practice that. Code aesthetics are a feature and they affect team and agentic coding performance, just not the kind you measure in the runtime.
> And be warned: some will resist this and surrender to the convenience of their current mental context, betting they’ll “remember” how they did it. Time will make that bet age badly. It’s 2026 — other AI agents are already in execution loops, disciplined to code better than that.”
Hard disagree: separating code from its context is exactly how you end up in the situation of needing to “remember”. Yes, helper functions and such can be useful for readability, but it's easy to overdo it and end up with incomprehensible ravioli code that does nothing terribly complicated in a terribly complicated manner.
The worst version of this I've seen is when every layer is like four lines long. You step into a function expecting some logic and it's just calling another function with slightly different args. Do that six times and you forgot what the original call was even trying to do.
Naming helps in theory but in practice half those intermediate functions end up with names like processInner or handleCore because there's nothing meaningful to call them.
One heuristic I use to avoid this exact problem is "minimize the number of places that the next poor soul has to look in order to understand how this code works", where place is loosely defined as about the number of lines of code that fit on a screen or two.
This has given really good results in terms of helping decide whether to extract these helper functions or not - they have to both be memorable enough in name and arguments that the code calling them can understand what's going on without always having to dive in, and also provide a meaningful compression of the logic above so that it can be comprehended without having to jump across many hundreds of lines.
It'd be great if IDEs can store a stack of functions currently being explored similar to what you get when debugging. Not breadcrumbs, but plain stack. Bonus points if you can store multiple stacks, and give them names according to the context.
Ah. I once worked in a team with a hard cyclomatic complexity cap of 4 per function. Logic exceeding the cap needed to be broken into helper functions. Many, many functions were created to hold exactly one if statement each. Well, the code was relatively high quality for other reasons, but I can't say this policy contributed much.
I think I agree with what you're getting at, though I usually phrase it differently: indirection is not abstraction. A good abstraction makes it easier to understand what the code is doing by letting you focus on the important details and ignore the noise. It does this by giving you tools that match your problem space, whatever it may be. This will necessarily involve some amount of indirection when you switch semantic levels, but that's very different from constantly being told "look over there" when you're trying to figure out what the code is saying.
Agree, and I would add that a bad abstraction, the wrong abstraction for the problem, and/or an abstraction misused is far worse than no abstraction. That was bugging me in another thread earlier today: <https://news.ycombinator.com/item?id=47350533>
Last time was a go shop, and let me tell you: that style mixes with go's error handling like spoiled milk and blended shit.
Oh gee, thank you for this wrapped error result, let me try to solve a logic puzzle to see (a) where the hell it actually came from, and (b) how the hell we got there.
Each part of the codebase is a separate self contained module with its own wrapping (boilerplate), except there's like 30 of them and you still have to understand everything as a whole to understand the behaviour of the system anyway.
Think of what ravioli are and apply that to the same code analogy as spagetti or lassagna. The code is split in tiny units and that creates too much indirection, a different indirection than spagetti or ravioli. The architecture feels fragmented even though there's nothing wrong with each piece.
> And be warned: some will resist this and surrender to the convenience of their current mental context, betting they’ll “remember” how they did it. Time will make that bet age badly. It’s 2026 — other AI agents are already in execution loops, disciplined to code better than that.”
Hard disagree: separating code from its context is exactly how you end up in the situation of needing to “remember”. Yes, helper functions and such can be useful for readability, but it's easy to overdo it and end up with incomprehensible ravioli code that does nothing terribly complicated in a terribly complicated manner.