Like most engineers who do a lot of contract work, I’ve had plenty of job interviews. I’ve had chats across desks, and over the phone. I’ve written programs on whiteboards and on laptops, and answered technical questions and non-technical questions, and solved puzzles. One thing I’ve never had, though, is an interviewer give me some code and ask me to talk about it, which is strange because my first real job at any site is always figuring out the existing codebase.
I think writing code and reading code (especially other people’s code) really are different skills that need practice. I often have to remind myself to do it more often. Of course, I’m not talking about reading code from beginning to end like a book. I mean understanding the overall architecture, then diving in and figuring out how it does specific things, to the point where you know which bits are not so efficient or secure, or how much work is needed to make it do new things.
Obviously, code reading skill is handy for the 99.999% of software jobs that involve code written by someone else. But here’s another thought: if you never read anyone else’s code, how can you expect to write code that’s readable by others?
Once upon a time I didn’t care about code readability. I’d write cryptic garbage and think, “Gee, I hope this code just works because I sure don’t want to look at this ever again.” It feels stupidly obvious now, but I had to learn the hard way that that was always the code I would end up having to reread for debugging.
Debugging my own code taught me why I should care, but most of what I do in practice to keep code readable is stuff I’ve learned from debugging other people’s code. That’s basically my litmus test for code readability. If I’m writing code and wondering whether it’s readable enough, I try to imagine it’s written by someone else (who quit five years ago or something), and it has bugs, and I’m the one who has to debug it. If that makes me uneasy, I know I’m doing it wrong.
A trap is confusing “readable code” with “code with lots of comments”. Comments can easily be a crutch for unreadable code, especially comments like “add one to x” that only exist to avoid reading the code in the first place. The most readable code I’ve seen only has high-level comments for why something is the way it is (or, more importantly, why it’s not some other way). A block of code might have no comments, then a single line might have a whole page. Rules like “every 5 lines must have a comment” are counterproductive because they encourage commenting at the same level as the code, instead of the higher level it needs to be done at.
Recently I came across some Python code a bit like this:
I changed it to something like this:
Which do you think is more readable? (Which is more robust against business rule changes around schedule
handling?) I prefer code that does what it means (and, for what it’s worth, reflection with
isn’t exactly a high-performance feature of Python or anything).
Other code styles I use include
- Being conservative about abbreviations, preferring to only use ones like
num_pagesthat make sense without any special context. Very short names should have very short scope so that they stay in context.
- Actively taking opportunities to give things meaningful names, like splitting code into functions, or assigning values to local variables.
- Avoiding mysterious action at a distance (which often comes from things like complex class hierarchies or global state), preferring to keep relevant context local.
- Creating meaningful types instead of abusing strings, tuples and associative arrays.
- Making assumptions and dependencies explicit.
In any case, lifting off the cover of a program once in a while and seeing how it ticks on the inside is a pretty good way to learn.