About the author
Tyler Adams joined the PullRequest reviewer network in 2020. Tyler has developed software and led engineering teams at a number of companies in New York and the Bay Area including Square, Pure Storage and Two Sigma.
Tyler runs CodeFaster, and be sure to follow him on Twitter @canardivore and check out his article How to Write a Good Code Comment
Imagine you’re designing a high-performance system. What hardware would you use? Would you use only general-purpose CPUs? Probably not, you’d also use GPUs. As high performing engineers, we also need to move beyond our general-purpose hardware and leverage specialty hardware. But our general-purpose hardware is not an Intel Xeon W-3275M CPU; it’s the part of our brain that handles abstract reasoning. Our specialized hardware is not an AMD Radeon RX 5700 graphics card. It’s our eyes. We’ll start by walking through a real-world example of using eyeballs to debug during code review and learn from it afterward.
A report from the field
A friend of mine is going through the greatest programming book for the first time. And like any great engineer, he wrote a bug. He knew there was something wrong in a cond statement. Here’s a stripped down version of his code:
(cond p1
e1
p2
e2
p3
e3)
He thought hard about it. Reasoning about what might be wrong. Looking at the definition. Reviewing the code. Back at the definition. Back to reviewing the code.
No progress.
He tried comparing it to a correct use of cond:
(cond (p1 e1)
(else e2)))
Looking at the correct example. Looking at his code. Looking back at the correct example. Back to reviewing the code.
No progress.
Then, he tried visually reframing the code by indenting each nested function call.
His code:
(
cond
p1
e1
p2
e2
p3
e3
)
Working code:
(
cond
(
p1
e1
)
(
else
e2
)
)
Aha! He saw the statements were shaped differently. The difference became immediately obvious. The second cond groups has parentheses that the first cond does not. The parentheses go around each “p-e pair”. Therefore in the first cond, he should group each “p-e pair” in parentheses. Bug debugged.
Analysis
Now that we’ve seen a particular example of debugging with our eyes, we can learn from it. At first, we had no idea what was wrong with our cond statement. We didn’t know where the problem was. It could be anything. Maybe the order was wrong. Maybe one of the p(redicates) was malformed. Who knows? Then, we reframed the situation. We turned subtle parentheses into flamboyant indentations. Our broken version was juxtaposed against a pristine working example. Instantly, our eyes found the working example’s extra parentheses. They screamed out, “Look at me, I’m different.” Once there, our brain took over the last few steps to finish up.
Here we see the secret to debugging with our eyeballs: visually reframing the situation. Once the situation is visual, our eyes are well-tuned for noticing oddities and irregularities. If we can go a step further and compare two similar but distinct visuals, our eyes will quickly spot the difference.
4 Tricks for debugging with your eyes
Rule of silence
“When a program has nothing interesting or surprising to say, it should shut up”
It’s easy to notice something odd if it’s the only thing on the page. If it’s hidden amongst 100 lines of useless information, we might miss it. The best way to capitalize on this is to change our programs to print nothing upon success. The second best way is to get rid of noisy success messages with a tool like grep.
cat logs.log | grep -v "STATUS: SUCCESS"
Spot the difference
Our eyes are very good at noticing differences. So, if we can turn a debugging problem into a “spot the difference” problem as we did above, our eyeballs will speed up our debugging significantly.
Shape it
The previous two examples work well for differences you’re expecting (an error, a known good example compared to a known bad example). How can we use our eyes to help us spot differences we’re not expecting? Shape.
Which difference is easier to spot?
1
1
1
1
1
7
1
1
1
or
X
X
X
X
X
XXXXXXX
X
X
X
Both represent the same data, a 7 hidden amongst 1s. But we can easily see XXXXXXX among Xs, even from a distance. If we can convert our “notice information you weren’t expecting” into a “notice a shape you weren’t expecting”, we are much more likely to find it.
What’s black and white and red all under?
A misspelled word! The spellcheck UX is a fabulous example of using color to help us debug with our eyeballs. Spoting mispsellings in an see of text can be though. We can’t see them. They look like ordinary words, but only when we think carefully (or look them up in a dictionary) do we notice an issue. But with spellcheck, when we misspell a word (which is like a bug), then below the word, it’s… red! Against white and black! It screams to our eyes, “I’m broken. Fix me!” And once our eyes alert us to the issue, we’re able to fix it.
Conclusion
Our eyeballs help us debug much more quickly. Once reframed, they spotted the error with our “cond” statement in a second. We have a bag of tricks to empower our eyes to help us review code and fix bugs. Next time we’re debugging, we’ll be ready. We’ll not only think, “What’s going on? What’s broken?” But also, “How can I visually reframe the bug? How can I make the bug easy to see?”
If you liked this, check Tyler’s article How to Write a Good Code Comment
He also runs the blog CodeFaster, and be sure to follow him on Twitter @canardivore