
Every course, mine included, is built around writing code. You are given a problem, you type a solution, it runs, you feel the small thrill of it working. That is the right way to learn. But it quietly sets up a false expectation, because it is not what most of the job actually is.
On a real team, you spend far more time reading code than writing it. You read the function you need to change before you touch it. You read the library you are about to depend on. You read a bug report and then read the code that caused it. You read your own work from six months ago and have no memory of writing it. Reading code is the main event, and almost no one is taught to do it well.
Why reading is harder than writing
When you write code, you already have the intent in your head. You know what you are trying to do; the code is just you spelling it out. When you read code, you have only the result — and you have to run the film backwards to reconstruct the intent that produced it. All the decisions, the things that were tried and thrown away, the context the author had and you do not, are gone. Only the final answer remains, and you have to infer the question.
That is genuinely hard, and feeling slow at it does not mean you are bad at programming. It means you are doing something that is rarely practised on purpose. So let us practise it on purpose.
Don't read top to bottom. Follow one thread.
The instinct with an unfamiliar codebase is to open the files one by one and read down the list, like a book. Do not. A codebase is not a book; it is a web, and read linearly it is just noise.
Instead, pick one concrete thing the program does — "what happens when a user logs in" — and trace that single path all the way through. Find where it starts. See which function it calls. See what data that function reads and writes. Follow it to the response. You will pass through only the files that matter for this one behaviour, in the order they actually run, and by the end you will understand that slice completely. Three or four traced threads and the shape of the whole system appears, far faster than skimming every file ever would.
Separate what it does from how it does it
When you read a function, resist diving straight into every line. First answer the larger question: what is this for? What does it take in, and what does it give back? A function's name, its inputs and its return value tell you most of what you need before you read a single line of its body.
def available_seats(show_id):
booked = seats_taken(show_id)
return all_seats(show_id) - booked
You do not need to read seats_taken or all_seats to understand this. The names tell you: available seats are all the seats minus the taken ones. You can keep reading the code that called this, holding available_seats as a known quantity, and only dive into seats_taken if and when you actually need to. This is how you read a large system without drowning: treat each well-named piece as a box you can trust until you have a reason not to.
Which, by the way, is the strongest argument there is for naming things well in your own code. The reader — often future you — is trying to avoid opening your boxes. Good names let them.
Read the tests
If a codebase has tests, read them early. A good test suite is the most honest documentation a project has, because it is executable — it cannot drift out of date the way a comment can without something going red. Tests show you how the code is meant to be called, what inputs it expects, and what it is supposed to do at the edges. "What does this function do when the list is empty?" is often answered more clearly by a test than by the function itself.
Get comfortable not understanding everything
Here is the part that takes the longest to accept: you will never understand all of a real codebase, and you do not need to. Senior engineers work productively in systems they understand maybe twenty percent of. The skill is not total comprehension — it is understanding the part you are touching well enough to change it safely, and knowing where the edges of your understanding are.
You build that by reading with a question, always. Not "let me understand this codebase" but "where does the total get calculated?" A question gives you a target and a finish line. Without one, you skim forever and retain nothing.
How to practise
Start small and deliberate. Take a library you already use and go find how one feature you rely on actually works under the hood. Read a pull request on a project you follow and try to understand the change before you read the description. Open your own code from a few months ago and see how much your past self left for you to reconstruct — then notice what would have helped, and do that for the next reader.
Writing code gets all the glory. But the engineer who can walk into unfamiliar code and quickly understand it is the one who can fix anything, join any team, and work on things far bigger than they could have written alone. It is a learnable skill. It just needs you to practise the half of the job the tutorials forgot.
Frequently asked questions
Why is reading code harder than writing it?+
When you write code you already hold the intent in your head. When you read it, you have to reconstruct that intent from the result alone, with none of the decisions or dead ends that led there. That reconstruction is a real skill, and it is trainable — it just rarely gets taught.
What's the fastest way to understand an unfamiliar codebase?+
Don't read it top to bottom. Pick one real thing the program does, find where that starts, and follow it through — the request, the function it calls, the data it touches, the response. Tracing one path end to end teaches you more than skimming every file.
Should I read open-source code to get better?+
Yes, but read with a question, not in general. Pick a small library you already use, then go find how one feature you rely on actually works. Reading with a specific target keeps you engaged and gives you a finish line, which skimming a whole repo never does.
Written by Rizwanul Haque
Software engineer with 13+ years in the industry, and the founder of RizTech Academy — a free tech-education initiative offering in-depth courses and mentorship, open to everyone.
Want to learn this properly?
The free courses take you from the basics to real, working software — no sign-up, no fees.