Published: April 25, 2022 • 3 min read
In Things You Should Never Do, Part I, Joel Spolsky narrates Netscape’s ruinous decision to rewrite their browser from scratch. This introduced the following concept to me:
“It’s harder to read code than to write it.”
I believe this. Today I’d like to explain why.
As an example, consider the “liking” feature of Today I Learned. This is a button under each Today I Learned post that you can click to announce: “I like this.”
When we explore TIL’s codebase, we see this method called when a visitor likes a post. I’m going to examine this method line-by-line and raise questions that I might raise while coding, as if I’d never seen it.
# app/models/posts.rb def increment_likes self.max_likes += 1 if self.max_likes == self.likes self.likes += 1 notify_slack_on_likes_threshold if likes_threshold? save end
This name suggests that
likes is a column on the model. If true, why do we
need a method? It’s not obvious.
self.max_likes += 1 if self.max_likes == self.likes
Okay, what is
max_likes? ‘Max’ as a prefix is pretty vague. Why are we
comparing that to
likes and only incrementing it when they’re equal? This
comparison would benefit from abstraction to a method like
new_max_likes?, or abstracting the whole line to
self.likes += 1
Incrementing the likes; I get this.
notify_slack_on_likes_threshold if likes_threshold?
So we’re notifying Slack about something called
likes_threshold? is true. This abstraction feels incomplete. Why can’t
notify_slack_on_likes_threshold know if we’re in the right state? Once
we refactor it, maybe we could give it name like
Why explicitly save? Could this be combined with the likes
That finishes the method. It’s short enough to appease Sandi Metz. But it’s doing a lot, with room to improve.
There’s a big piece of information missing from this analysis: this method was written to help us send an idempotent notification to Slack.
When we built TIL, we wanted to know which posts were popular, so we added liking. We chose to send messages to Slack when these likes crossed important thresholds (e.g. 100 likes).
max_likes came from this. Before it, if somebody clicked ‘like’ at nine
likes, bumping the count to ten, then un-clicked it, and then clicked it again,
our code would send two Slack notifications. We needed idempotency, hence
max_likes, which tracks the highest amount of likes that has ever been for
That feature was important, because it proved that our writing was having an impact. As we saw likes increment, we saw what resonated. It’s a little thing that helped made TIL a hit.
Someone reading this code would not have this context.
Practically, what happens when this context is absent?
If you’re rewriting an application from scratch, these questions hardly ever get asked. Given you even have the code, you can’t take the time to explore every method in this detail. You’re speed-running. Whoever wrote the feature is gone. If it is used, everyone takes it for granted.
In the unlikely event you do read this method, you’re going to say: “What’s happening here? I don’t get it. This isn’t MVP” and move on. This kind of omission is the rule in a rewrite. You’re only building the stuff that’s ‘important’, with bias, ignorance, and inattention coloring that definition.
As gnarly as legacy code is, it works and people have to come to rely on it. That is worth our attention. When we read legacy code thoughtfully, we elevate our profession.
At AWS they almost never retire an API. Once it’s in production, it’s supported forever. Many companies can’t act this way, but the spirit prevents thoughtless mistakes like breaking the likes notification.
I think code reading is the highest programming skill you can have. Scanning a line, putting it in words, precisely jumping to a function definition in multiple codebases, returning without getting lost, and adding to the bigger story you’re telling yourself or those participating— few programmers do this well. I want to encourage us all to work on being better code readers.
“It’s harder to read code than to write it.” What does this statement mean to you?
Thanks to Josh Branchaud for this blog post idea.
Get better at programming by learning with me. Subscribe to my newsletter for weekly ideas, creations, and curated resources from across the world of programming. Join me today!