Hacker News new | ask | show | jobs
by chewbacha 26 days ago
I did this for two weeks on a side project and still ended up in a situation where I did not have a mental model of the codebase.

There’s no way build that model without building it yourself. I’m more convinced then ever of this.

6 comments

Unfortunately I ran into the same issue even before AI.

The forgetting curve means that my mental model lasts not much longer than the initial building period.

As for how to rebuild it, I haven't figured that part out yet.

Sounds like you wrote very poor quality (edit: or trivial) code, or you’re exaggerating a bit for effect.

I too forget the details of most of the code I write, but the most important 10-20% of the code that I write encodes my mental model of the problem I’m trying to solve. Sometimes it’s a class representation of a digital or physical entity. Sometimes it’s a job with tasks that map to subproblems. Those abstractions almost immediately launch me into the mindset of my former self, even years (or a decade!) after the fact.

AI-generated code does not tend to create those kinds of abstractions in my experience. It will likely, with encouragement, solve the problem you’re asking it to - but it won’t magically cause you to understand how to solve the problem. You must take the initiative to understand it yourself. You are the camel that the AI has taken to water, and it can’t force you to drink it.

So the way I write code is that, my understanding is local. Okay, we need a function that does this (high level). It'll call these functions to do that. And then I just continue until there's nothing left to write and the thing works (after a few rounds of debugging).

I understand each piece and what it talks to. But I can't hold them all in my mind at once, because there's too many pieces. (I think chunking helps here, but it seems to require a certain level of fluency with the entire codebase that I'm not sure it's feasible to hit with anything past a certain line count. I am working on this new memory software though...)

The transformer on the other hand, just loads it into context (they can do about 10K LoC these days without performance degradation), cross references everything against everything (that's how the transformer works! That's why they're so expensive) and just tells me what talks to what, what the full chain is, and also btw you have 3 bugs you didn't notice because they involve how distant parts of the chains interact, you're welcome!

I've been looking for ways to build up that mental model. The Feynman technique seemed like a good place to start. I did it on a section of my codebase. It took half an hour of poking around to connect all the pieces. The transformer was able to do it instantly.

I'm not sure if there was added value to me poking around manually or if those 30 minutes would have been better spent just memorizing what it told me.

(After verification of course! To clarify, I don't think they're infallible, but their perception is broader than ours due to how they're structured, and I'm learning to utilize that more effectively.)

Also, in the absence of that costly verification, the model my Feynman technique produced turned out to be wrong (though it sounded correct!). So I'm leaning in the direction of, the way to actually verify your mental model is to make a modification to the codebase. Make reality push back!

--

On some projects/subprojects I do build an explicit mental model beforehand, and then I do generally remember it pretty well, at least for a while. Others take a more iterative approach to the design. (I'm on the 5th damn iteration of my netcode right now.)

So there's two distinct issues here, the model building process and the human forgetting curve.

That’s fair I guess. I’m pretty consistently surprised by the wide variety of tasks that everyone under the “programming” moniker tackles. I consider myself a programmer by trade, even though I’m not a SWE. Your first paragraph couldn’t really be further from my personal experience. I haven’t thought in terms of functions in years, mostly “jobs”, “tasks”, “workflows”, “data flows”, “modeling”, “labeling”, etc.

Some people really do have jobs that I wouldn’t be surprised that LLMs will nearly completely automate away. And those people will be forced to move “up the stack” in terms of abstraction… but that’s already where I’m at. And LLMs are helpful, but I don’t feel threatened by them at all. If they take my job, I think computers will be declared obsolete. No more keyboards and mice.

> As for how to rebuild it, I haven't figured that part out yet.

Just do some work with the code. If I go back and try to add a feature or fix some bugs on code that I have not worked with for a long time I find it much quicker to build up a mental model of it than code which I have never worked on previously.

Yeah. Ebbinghaus found this in his work on memory in the 19th century. Even after something has been forgotten, re-learning it goes more quickly, as a function of how many times it has been learned already.

I'm developing a new memory system that functions as an L1 cache for the human mind, taking the opposite approach of Anki and showing you things you want "top of mind" as often as possible. (As opposed to as rarely as possible, which is the standard approach in the memory space these days!)

If you were working as a manager on a large project, how would you build a model? Something where your position requires you to have an overview of the project but not necessarily to actually write or review much code.
I am not able to find it now, but there was an amazing story recently from the 60s or 70s where an engineer was in exactly this position. His team was building a new, complex, ambitious operating system, but it was late and over budget and didn’t work. It nearly wrecked the company. He talks about hitting rock bottom and asking himself what went wrong, and one of the fathers of computing (can’t remember which) shouts from the hallway in passing, “that’s easy, you didn’t understand what your people were doing.” So the guy turned it around by implementing a new rule: he had to understand every line of code his team wrote. They started over with the company’s existing OS in use by customers and implementing a few of the most requested features. Much less ambitious, but it actually shipped. Gradually they achieved all their goals by upgrading the existing system.

The “I must understand every line” constraint didn’t sound like a power trip that succeeded because the guy was such a brilliant code reviewer. I think it was a blunt instrument that enforced simplicity.

I guess what I’m saying is, I reject the premise of having technical oversight without writing or reading much code.

As with anything. Either you can go full-speed without much understanding and hit a wall when you need to understand stuff or you can go a manageable speed and actually understand the codebase.

I don't think we can do both. The difference is that it's optional now depending on the project and the audience.

I never said you wouldn't have to read code. I was asking a question to get answers about how people would achieve having an oversight if it was humans writing code that they were managing rather than agents.

As for your suggestion, understanding every line might have worked in the 70s but even pre-agentic modern coding it's not possible for any large project with dependencies even if you are directly contributing code yourself, so I'm not sure how useful your idea is.

There's definitely cases where you should have that aim - writing a low level maths or graphics library, for example. But most people are not doing that.

Perhaps my "reject the premise" comment was a bit too provocative. I didn't intend to start an argument. I wanted to share a story of a person who was put in the position you described (working as a manager on a large project, required to have an overview of the project but not necessarily to actually write or review much code), failed miserably, changed the rules of engagement (partly by reviewing code), and subsequently succeeded. So my _personal_ answer to your question of how to build a mental model in that scenario would be to do something in the same vein as that story. Not necessarily _exactly_ what that guy did, but I think the principles still apply today. Nothing really changes.
I've been experimenting with the Feynman technique on codebases. However the issue I run into is that, you need hard feedback to verify your hypotheses.

I was satisfied with my own explanation of how something worked but it turned out to be wrong.

LLMs help here (the transformer is good at seeing the big picture, at least on smallish codebases), but the best thing I found so far is just modding.

Actually making a change to the code is the best way to get hard feedback about your model.

As a manager you try to hire people who can build that model so you don't need to, sadly you can't do that with an LLM yet.
My understanding is that this is still an unsolved problem. At some point you lose touch with the code and you start working with a mental model that’s subtly inaccurate. You just sort of hope that the people below have are competent and are building stuff that matches your mental model (that you’re communicating well!).
You can just ask the model to explain the code to you.
Yes, and you will still not understand as well as if you had built it.
You're similarly not limited by what you can readily understand.

Being comfortable with the default level of trust is one thing. Command of the code is another.

By running the generated code at all, you've found some acceptable level of trust and comfort.

Scaling that comfort and trust seems to be the obvious move.

We often don't understand the code we wrote 6 months ago.
For me, the issue is that the model can explain what the code IS, not what it’s supposed to be or aspiring to be. The code doesn’t explain the original constraints (because it already fits within them) and it doesn’t show the tried and discarded approaches. It’s like rewriting a MIDI roll back into sheet music. Or better, it’s like the difference between being the author of an opera, and having read reviews of it.
One of my favourite things to do is to ask the models, "what does this code do and why?" They are usually not far from the truth. From the perspective of a LLM that has been trained on all of the public code on GitHub, issues, and pull requests, your code and its intents are not that unique. They can see patterns in the code that point to the purpose. The constraints that shaped your code are the same constraints everyone else had.

Developer intents and aspirations aren't unique either. And in an LLM-written codebase, the chat history and prompts are available. The constraints, the rejected approaches, the goals. Users ask the models to write MD files that directly state their intents and aspirations for the ode.

I'm not so sure. I think you can, you just need to intentionally drill into what you don't understand and it's exhausting. What I do agree with though is that I can't seem to build the ability to build it myself the same way as I would if I wrote it.

For example, I know my mental model works because I know what change I should do in order to get an effect and when I do the change, I get what I expect. But if I were to build myself something similar, I could not build it because the approach is somewhat out of my reach, I know it sounds weird, but it's hard to explain.

That's why I like to build a complete feature and the infrastructure myself first, so the AI will have a picture of how the code should look and where it should live.

Or I use the short-leash method and I will instruct the AI build infrastructure first, without even talking about features yet.

Code review works for me.