← All writing
Craft · · 7 min

Reading a codebase

Being lost is a constant, not a signal. Write the questions down while you're still ignorant enough to have them.

Git Culture

Four years ago I inherited a store with 200-line functions in it, and I wrote up the order I read things in: the site before the code, the git log before the files, the entry points, then the templates, then the logic.

I still read things in roughly that order. What I’d change is the emphasis, because I presented it as though the order were the insight, and having done this maybe 15 more times since, I don’t think it is. Any consistent order would probably work. The point is having one at all.

The feeling is not information

Here’s what I actually do without a procedure, and what I did for about six years.

I open the project. I feel a small unpleasant jolt of not-understanding. So I open a file, because opening a file feels like progress. It doesn’t help, because a file means nothing without context, so I open another one. 20 minutes later I have 11 tabs open, I’ve read fragments of all of them, I understand none of them, and the not-understanding has now compounded into something closer to dread.

That’s not a research method. That’s an anxiety response with a text editor attached.

The thing that took me embarrassingly long to accept is that the feeling of being lost in an unfamiliar codebase is a constant, not a signal. It’s there in hour one whether the code is beautiful or appalling, whether you’re good at this or not, whether the project is well documented or a swamp. It tells you nothing about the code and nothing about you. It’s just what week one feels like.

The feeling of being lost is a constant, not a signal. It's there whether the code is beautiful or appalling, and I spent years reading it as a verdict on me.

I spent years quietly reading it as a verdict, which made me want it over with, which made me rush, which is precisely the thing that makes it take longer.

A procedure fixes that, and not primarily because the steps are optimal. It fixes it because when you’re on step three of six you know you’re on step three of six, and “I don’t understand this yet” becomes a schedule rather than an accusation.

Ship something on day one

The single most useful thing I’ve added since 2016, and it’s slightly counterintuitive.

Before understanding anything, make a change and get it live. A typo in the footer. A copy tweak somebody’s been asking for. Something so small it cannot be wrong.

Because the thing you most need, and the thing no amount of reading gives you, is the loop: how do I get a change from my head onto the server. Where does the code live, how do I run it locally, what does the build do, how do I know it worked, who has to approve it, how long does it take. That’s five separate pieces of knowledge and every one of them is invisible in the source.

And you find out immediately whether the loop is broken, which it very often is, and which is the actual first task rather than a distraction from it. On two projects the “change a typo” exercise took a day and a half, and in both cases that day and a half was the most valuable work in the first two weeks, because everything after it was faster for everybody.

Write your questions down while you’re still stupid

The other addition, and it’s the same argument I made about READMEs a few years back, wearing different clothes.

Keep a running file while you read. Not notes on what the code does, notes on what confused you. Every “why is this here,” every “where does this come from,” every “I assumed X and it was Y.”

Those questions have a very short half-life. By week three you will have absorbed all of them, and absorbing them feels like getting good and is actually the loss of the only outsider’s view this project will get until the next person arrives, who will be equally silent about it for exactly the same reason.

notes.md, week one
- Two "helpers" directories. app/helpers is used, lib/helpers is not. Why?
- Nothing in here explains why the invoice PDF is generated on a different server.
- `is_legacy` flag on the customer table, set on ~40% of rows. Nobody knows.
- Build works from clean but only if you run it twice. WHY does it work the
  second time.
Markdown

At the end of the first month, half of those have answers and the answers go in the README, which is the onboarding document the project never had, written by the only person qualified to write it, which is the newest one.

The three things I’ve added to the reading itself

Not a new order, just three additions to it.

Rank the files by churn. The git log tells you which files change; a quick count tells you which files change most, and that ranking is a better map of where the project actually lives than the directory structure is.

terminal
git log --format=format: --name-only --since="2 years ago" \
  | sort | uniq -c | sort -rn | head -20
Shell

The top of that list is where the work happens and where the bugs are. The bottom is either rock-solid or dead. Both facts are useful and neither is visible by looking at the tree.

Read the tests, if there are any. Tests are the only documentation that’s executable, so they can’t have drifted, and a test suite tells you what the previous authors were worried about, which is a genuinely different and more useful thing than what the code does. And if there are no tests, that’s information too, and it changes how bravely you’re allowed to refactor.

Read the support inbox before the code. Or the issue tracker, or whatever passes for one. Six months of “the site is broken” emails tells you exactly which parts of this system are fragile, and it’s usually not the parts that look worst. It’s also, per an argument I keep having with myself, the only list you’ll get of what the software is actually like to use.

Pick a procedure

The order I gave in 2016 is fine and I’d still recommend it. Site, log, manifest, entry points, templates, logic, with a question in hand rather than a hope of understanding.

But if I were writing it now I’d lead with the other thing: pick a procedure, almost any procedure, and follow it even when it feels slower than diving in. Because diving in isn’t faster. It just feels like doing something, at the moment when doing something is what you want most and is worth the least.

Read similar posts
6 min

What an RSS feed is for

Somebody who has been building websites for two years asked me what the orange icon in the footer did, and I gave an answer that was mostly about 2007, which was no use to them at all.

6 min

The blogroll

I found a writer I now read constantly because of a link at the bottom of somebody else's post, and it took me a day to work out why that felt unusual, which is that almost nothing reaches me that way any more.