Of course, now I'm not in a programming job, so I can only imagine I've gotten worse.
Of course, now I'm not in a programming job, so I can only imagine I've gotten worse.
So, I think it helps to do more than just passively "read" it. I might create a private branch, run the sucker with lots of print statements, comment the hell out of it, take copious notes in org-mode, draw diagrams to leverage my visual systems, etc. (It might feel silly, but no one's watching.)
Running it repeatedly (with print statements) allows me to form little hypotheses and test them. The idea is to approximate having a REPL. Something like emacs helps to automate this as much as feasible.
A unit test will tell you if you know what output a function should give for a given input, that it does. Ermm, brilliant, but what if that function isn't on your code path anyway? And assuming that you already understand the program well enough to create any state the function expects if it's impure. Above poster has drunk too much Kool-aid and is suffering from Golden Hammer Syndrome ;-)
Context makes it so much easier. In the real world there is usually a purpose to code, and good code has a cohesive metaphor you can understand before you start reading. Practice eventually makes the syntax second-nature, but I found being able to understand the context and subtext of the code is a much bigger boost.
I took a poetry class in college and found that learning to read poetry helped me become more fluent at reading code. Instead of reading it like prose, from start to finish, reading poetry is about building a mental castle of what the poet is talking about, and then the actual words fill in the important details. Plus you learn to pick up on repetition, rhythm, deviations from established patterns and is-a relationships ;-)
I recently started programming at work after at least a decade of mostly not programming at work. My experience so far has been that reading code is easier than writing it, at least when an unfamiliar SDK is involved.