Reading code you didn't write
You will spend far more of your working life reading code than writing it — a teammate's pull request, a library you depend on, a project you just joined. Reading unfamiliar code without panicking is a trainable skill, and it is tested constantly in real jobs and technical interviews.
Reading is most of the job
When you write code from scratch, you already know what every line is for. Real work rarely looks like that. You fix a bug in a file someone else wrote two years ago, add a feature to an existing app, or figure out why a library behaves a certain way.
Beginners often feel that not instantly understanding someone else's code means they are not good enough. It doesn't. Experienced engineers also start confused; they just have a method for getting un-confused.
The method in this lesson is simple: find where the program starts, follow one path through it, read names before details, and check your understanding by predicting what will happen. You do not need to understand every file to be useful.
Start at the entry point
Don't open files at random. Every project has a place where it begins, and everything else is reached from there.
- Read the README first: what the project does and how to run it.
- In a JavaScript project, open
package.json. Thescriptssection shows commands likestartordev, and themainfield often names the first file. - Look for files like
index.js,main.js,app.js, orserver.js. - In a web framework, the folder structure usually tells you where routes or pages live.
Once you find the starting file, skim it for what it imports and calls. That gives you a map of the major pieces before you read any of them in depth.
Follow one path, not every file
Trying to understand a whole codebase at once is how people get overwhelmed. Instead, pick one concrete thing that happens — "what runs when the user clicks Add to cart?" — and trace only that.
Start where the action begins (the button's click handler, or the route for that URL) and follow each function call to where it is defined. Your editor makes this fast: "Go to Definition" jumps to a function, and "Find All References" or a project-wide search shows everywhere it is used.
Keep short notes as you go, like a trail of breadcrumbs:
handleAddClickcallsaddItem(cart, product)addItemreturns a new cart and callssaveCartsaveCartwrites to localStorage
Ignore branches that are not on your path. You can come back to them later.
Read names and signatures before bodies
You don't need to read every line of a function to use what it tells you. Start with its name, its parameters, and what it returns. Often that is enough to keep following your path.
function indexById(users) {
const byId = {};
for (const user of users) {
byId[user.id] = user;
}
return byId;
}
The name and the return already suggest this turns a list of users into an object you can look up by id. Reading the loop confirms it.
The same goes for code from libraries. If you see a helper you don't recognise, check its documentation for what it takes and returns, and treat it as a black box. Diving into library source is rarely the first step.
Predict, then verify
The best way to test your understanding is to make a prediction before running anything. "If I call this with an empty list, it should return an empty object." Then check it: run the code, add a console.log, or step through it with the debugger.
let count = 0;
function increment() {
count = count + 1;
return count;
}
increment();
increment();
console.log(count); // what do you expect?
When your prediction is right, your mental model is confirmed. When it's wrong, that is the most valuable moment: find the exact line where reality differed from what you expected. That's where your understanding had a gap.
Also resist the urge to rewrite code that looks strange before you understand why it was written that way. There is often a reason.
What to do now
Find a small open-source project on GitHub (a few dozen files at most) or a classmate's project, and read it before running it:
- Read the README and
package.json, then find the entry file. - Pick one feature and trace it from where it starts to where it finishes, writing a breadcrumb note for each function call.
- For three functions, write one sentence each describing what they take and return, based only on names and signatures. Then read the bodies to check.
- Make one prediction about behaviour, run the project, and verify it.
The goal is not to understand everything, but to understand one path well.