Robert C. Martin has argued in Clean Code that developers spend far more time reading code than writing it — a ratio he estimates at roughly 10:1. According to SonarSource, less than a third of a developer's week goes toward writing new code. The rest — onboarding, code review, debugging, legacy maintenance — is mostly reading. Yet almost no one trains this skill deliberately.
Code is compressed thought. A single function can encode hours of design decisions, implicit constraints, and domain assumptions — none of which appear in the syntax. When you read prose, the author is trying to communicate with you. When you read code, the author was communicating with a compiler. You're a third party eavesdropping on that conversation.
This is why reading code slowly has nothing to do with intelligence. It has to do with the mismatch between how code encodes information and how human memory works. The techniques below work with that mismatch instead of fighting it.
Tests are executable documentation. Before reading a function, find its tests. They show you the expected inputs, the expected outputs, and the edge cases the author was thinking about. A well-tested function becomes nearly self-explaining: you see the contract before you see the implementation.
If there are no tests, that itself is information. It means the code may have implicit assumptions the author never wrote down — read with extra skepticism.
Clear names make it easier to form and retain a mental model of the code. When you encounter a block of unfamiliar code, pause and write a one-line summary of what you think it does — even if you're only 40% confident. This forces your brain to commit to a hypothesis, which speeds up the moment you either confirm or discard it.
This is the core of the Feynman technique applied to code: if you cannot name it, you do not understand it yet.
Beginners follow execution order: line 1, line 2, line 3. Experienced readers follow the data: what is this variable when it enters the function? What can it be when it exits? Where does it get mutated?
Pick the most important data structure in the function and trace its lifecycle. Everything else in the code is either transforming that data or deciding whether to. This mental model can significantly reduce how much you need to track at once while reading complex code.
Code has at least three useful reading altitudes: the system level (what does this service/module do?), the function level (what does this method accomplish?), and the expression level (what does this line do?). The mistake most slow readers make is staying at expression level the entire time.
Practice consciously switching altitude. When you get lost in expression-level detail, zoom out: read the function signature, the class name, the module imports. Get your bearings, then zoom back in.
Expert chess players don't see individual pieces — they see configurations. Expert readers don't see individual lines — they see patterns: a retry loop, a repository pattern, a null-object, a strategy, a builder. When a pattern fires in recognition, you don't need to re-derive what it does from first principles.
The way to build this vocabulary is deliberate exposure: read code you didn't write, in languages you know well, and force yourself to name the pattern before you look it up.
Code is frozen at a point in time; git history is its biography. Before spending 30 minutes reading a complex function, run git log -p on the file. The commit messages tell you what the author was trying to do. The diffs tell you what changed and why. Often, five minutes of git history tells you more than 30 minutes of reading cold.
The act of explanation surfaces gaps in understanding that passive reading hides. You can read a function three times and feel like you understand it, then try to explain it and discover you cannot. The explanation attempt is not a test of whether you understood — it is the understanding itself.
This is why code review comments, PR descriptions, and onboarding docs make you a better developer: they force explanation. If you don't have a colleague to explain to, write it down. A rubber duck works. So does a practice platform that scores your explanation.