It's hard to read and parse code you didn't write

Published on

It’s hard to read and parse code you didn’t write.

I’ve been working on a number of projects recently, and one pattern has repeated.

The more code I try to review at the PR stage, the less I feel like I really understand what I’m shipping.

It’s hard to get a handle on how it works, where the pitfalls are, how it ties in with the rest of the system.

I know, ‘duh’, right?

This becomes an urgent problem in a world where AI is writing more and more of the code we ship.

As the genie (Kent Beck’s name for the LLM) generates more code, our job becomes a lot more about reading code than it does writing it.

And that’s tricky.

Because without writing the code it’s harder to build up a mental model of what the code’s doing, why, and how to manage it over time.

But that doesn’t mean you have to give up, write a few prompts, ship whatever AI throws your way.

As a developer, using LLMs, you have tremendous leverage.

You know what makes good systems work, how to architect solutions, how to separate responsibilities and write code that’s easy to maintain and extend over time.

But that advantage fades away very quickly when you throw a prompt Claude Code’s way and then try to review the resulting code.

(sooner or later you’ll get fed up of trying to read the LLM’s code and just sign it off anyway… it’s human nature to take the easiest path).

Regain your advantage

Remember all that hard-earned knowledge and experience you’ve earned, building software for all these years (before AI came along).

It’s your biggest advantage. The trick is to use that knowledge and experience, before AI writes the code.

Here are a few stages I work through for any sizeable piece of work with AI.

Get clear about the why (the requirement)

AI makes it easy to churn out a lot of code, but not all features should be built.

Possibly my favourite task for AI is to use it to get clear about what I’m building, and why it needs to exist.

Ask your AI to go back and forth with you to understand what this thing is that you’re building, why it matters, and what it looks like if it succeeds.

(Check out Matt Pocock’s grill me skill, as one way to do this).

Bonus points here if you work with the LLM to establish how you’ll measure whether it actually worked when you’re done (think metrics!)

Research

I’ve lost track of how many times an LLM has come up with an idea that I would never have thought of (and it turned out to be a good option).

Once you’re clear on what you’re trying to achieve, task AI with researching how to achieve that goal.

Ask it to ground itself in the current code (if you’re working on an existing system) but also research, more broadly, options for achieving what you’re trying to achieve.

Far better to throw some tokens at this up front than dive into building the first thing you think of, only to have to rework or entirely rebuild it later.

Design the architecture

If you’re working on an existing system, it already has clear architectural choices baked into the code.

But now you’re trying to change something, and that might need a new piece, or changes to an existing part of that architecture.

Ask your AI to raise the important questions that need addressing to plan where this new thing fits in, and work with you to answer those questions.

I do love a good diagram! Get the LLM to draw you pictures (ask it to use sequence diagrams, and other Mermaid-style diagrams to outline the main moving parts when it asks you questions).

Design the program

A lot of people stop at architecture, but there’s another level, before you bury yourself in thousands of lines of AI-generated code.

Task the LLM with working with you to figure out how this change fits into the existing code.

Not architecture (we’ve done that) but the level just below that.

Here you can use call stacks, file tree diffs, class/record/interface signatures.

Essentially a kind of blueprint for what changes it’s going to make, but not down to the level of individual lines of code.

The shape of the code changes, not the actual code itself.

The big unlock here is that you can read a few hundred lines of documentation at this level, and get a good handle on what’s changing.

Which gives you much more leverage over what the AI’s about to do, than trying to parse 2000 lines of code once they already exist.

Slice the work up

Finally, get the LLM to slice the work up into vertical slices.

I’ve been doing this for months now, and it makes a huge difference to both the quality of the code the AI generates, and how easy it is to course-correct it as it works through a feature.

Vertical here means work that delivers some useful part of the feature, vertically through the stack.

Maybe a button that calls an API endpoint that touches the database.

LLMs love to work horizontally (build out all the DB, then all the API, then all the UI) so you have to explicitly tell it to slice in smaller verticals.

In Summary

Notice this isn’t a set of magic prompts, or skills you have to go and install.

As new models come and go, they’re increasingly good at taking goals and running with them, often doing better without a thousand skills and agent.md instructions to follow as they go.

But, they’re still prone to writing whatever code they think will work, with little understanding of whether it’s good, or bad.

And there’s little sign they can understand the architecture of a system over time, the strategic side of programming, where you evolve a system carefully, factoring in all the pressures on it, to deliver something valuable at the end.

So keep the reins on the LLM. Get involved and steer it before it writes the code (because catching up afterwards is a lot harder).

Your skills aren't becoming obsolete. They're becoming essential.

Practical engineering principles for building software that works - with or without AI.

    Join 6,000+ developers. Hype-free.
    Next Up
    1. How you ship is everything
    2. Use AI to help YOU refactor your code
    3. When AI goes down a rabbit hole, use it to your advantage