I grew up, as a software developer, in the world of Perl. Perl’s motto is There’s more than one way to do it, (abbreviated to TIMTOWTDI and pronounced: Tim Toady).
As the thinking goes, this flexibility allows the programmer to write more concise statements, as well as choose a style that fits the context, or their whims.
But is this a good idea?
I distinctly remember the day I was trying to explain some Perl code to a colleague. The beautiful one-liner ellegantly iterated a list through a map function, and utilized the a subtle side effect to trigger an update to a variable, which was later read for its state.
After stepping him through everything it did, and him still shaking his head, I re-wrote it into a 3-line form that anyone could understand.
I’ve come a long way since then.
I once felt that writing short, clever code was the proof of my superior coding ability.
But what value is short, clever code that nobody understands?
People are usually the most expensive part of any IT system, so we should optimize for people’s time.
This means writing readable code, rather than clever code.
This usually means writing readable code rather than efficient code.
The same principle applies, of course, to non-code artifacts as well. Config files, diagrams, documentation. Optimize for readability.
Readability should usually be the first priority in any technical artifact you write. Of course there are exceptions, and I’ll talk about some of those in the coming days.
It’s harder to read code than to write it.
— Joel SpolskyIndeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.
— Robert C. MartinAny fool can write code that a computer can understand. Good programmers write code that humans can understand.
— Martin Fowler
If you enjoyed this message, subscribe to The Daily Commit to get future messages to your inbox.
Top comments (8)
Wouldn't comments solve the problem? That's what I do in my Perl: you need to grok what
map
andgrep
so, but if I stream a bunch of them together, I'll use whitespace and comments to clarify what's going on.Comments allow you to use the more efficient code and also to "teach a man how to fish". Why do we insist on dumbing down languages instead of smartening up programmers?
Comments are a really bad way to solve this problem, because comments are easily ignored, easily separated from the code they reference, and frequently fall out of sync.
Good code should be easily read and understood without comments. If you need to explain your code with comments, it means your code is confusing. As I've written before: Comments are like appologies to the next programmer: jhall.io/archive/2021/02/14/commen...
There are of course appropriate uses for comments. But they should almost always explain the WHY of code, not the HOW of code.
It depends. There's a tension between the number of bugs in code, and its readability. Powerful languages like Perl allow you to get more done in fewer lines, and that's a Good Thing. Bugs are proportional to the number of lines, not the number of things those lines get done. So powerful, correct code is terse. Readable, verbose code is buggy.
So there's a judgment call. If I write something that's powerful but terse, and I don't want to expand it into a buggy monstrosity of nesting and logic, I'll add a comment that documents not the WHY or the HOW but the WHAT. Nine times out of ten I'll put it into its own subroutine. I write lots of very short subroutines. Then the subroutine name becomes the comment. I write long subroutine names!
My own guideline for when to make the judgment call is if the terse code is readable for an experienced programmer, I'll keep it, possibly with added comment or broken out into its own sub. If an inexperienced programmer would need to puzzle over it, well, that's part of becoming an experienced programmer. But if even an experienced programmer would need to puzzle over it, then it's gone too far down the terse plughole and needs to be broken out a bit.
TL;DR write self-documenting code, but don't be shy to show your chops.
Aside from that, readability is not primarily about reducing bugs (although it may help with that). It's about reducing the cognitive burden to understand the code. It's about optimizing for developer time over machine time.
My rule is to optimize my code for the least experienced developer who is likely to need to understand it. For most projects, that usually means optimizing for people with bootcamp graduate level understanding. In some cases, it's fine to optimize for "experienced programers" (whatever that means in context).
I'd love to see some reference for your claim that "Bugs are proportional to the number of lines, not the number of things those lines get done. So powerful, correct code is terse. Readable, verbose code is buggy."
There's a good discussion here - mayerdan.com/ruby/2012/11/11/bugs-...
And some more sources here - stackoverflow.com/questions/289857...
Nothing is ever absolute, readability vs terseness is a trade-off. But my point is that readability is not as clear a win as people assume. If you are asking your best developers to write to a standard that is easily understood by your least experienced developers, then the benefits you gain from making life easy for beginners are costing you by reducing the efficiency of your best developers, and by introducing extra bugs because of the extra lines of code.
Thanks for the links.
I don't see supporting evidence for the claim in those links.
What I do see, from SO (and referenced in the other):
In the Mayer piece:
He appears to be making the claim that "long, verbose, duplicated, over-abstracted" code is more readable. I disagree. Of course "readability" is subjective, so if someone thinks that muddling through extra abstraction layers is "more readable", then I guess I can't argue with thier opinion.
Then he goes on to explain how they reduced cognitive load by simplifying the code.
To me, reducing cognitive load is the practical definition of making code more readable.
So I think he and I are advocating for the same outcome, but with different terminology. And IMO, his terminology is confusing, if not backwards.
Now all that said, I'm still doubtful of your claim that terser code inherently leads to fewer bugs. But I can't say conflusively that you're wrong, either. It certainly seems counter-intuitive, but then the best ideas often are.
I'll need to see more data.
But let me ignore all that for a moment, and take your argument at face value, and assume that more readable code == more verbose code == more bugs.
This would naturally lead to a balancing act. Not much different from the trade-offs often made between "readability" and "performance".
I would still tend to weigh readability higher, for the parts of code that change frequently, because they are read the most often.
So I don't think this changes anything fundamentally. It may tilt the scale slightly toward less readable code on a few edge cases. But I don't think much.
It would really depend on how much your code bloats by making it "readable". Let's say, turning a 1,000-line function into 10 100-line functions. This will probably bloat the code by, say, 5%, for the extra function calls.
Is a 5% increase in bugs worth it for code that's easier to read, reason about and, ironically, debug?
Of course it depends on particulars. But in general, probably it is, I expect.