Once, when looking for a programming job, I applied for a job I didn’t get. That’s not really surprising – I was just starting out, and there are lots of rejections on the way to any success. But the mistake that eliminated me from the applicant pool is a special case of a general human bias, so I want to write about it, in the hopes that I’ll save some of you from making a similar mistake: I accidentally avoided a difficult thing, even though I knew it was there and knew it was a difficult thing.
I think humans carry a strong temptation to avoid hard things, or at least to avoid certain things. A friend once remarked during college, “You can tell I should be studying for exams, because my room is very clean, and I balanced my checkbook, and I cleaned out my closet.” Her point was, “You can tell that I’m avoiding a difficult task, because I am being unusually diligent in easy, low-priority tasks.”
Joel Spolsky made a similar point about buying colored folders when he should have been doing something important. Paul Graham describes a related phenomenon he calls schlep blindness, by which he means the difficulty humans have in seeing difficult tasks as opportunities, or even seeing difficult tasks at all.
Two books on the subject that I highly recommend, are Angela Duckworth’s Grit and Matthew Syed’s Black Box Thinking. These books both touch on why some organizations and people benefit from mistakes, that is, they learn, grow, and keep going, and some do not. I think that, in large part, it boils down to a willingness to confront head-on whatever the problem is.
So back to that time I didn’t get a job:
I was pretty excited, because the features I tested worked. Hurray, I thought, I’m calling this API like a real programmer. Look at these little success messages when the database update succeeds, look at these crisp validation messages when the form is in a bad state and can’t be submitted.
In the back of my mind, I knew that updating a user’s actual login credentials via my application was potentially problematic, because it would make the local data about the log in be out of date with the API I was calling, and for some reason I just didn’t test that part thoroughly. I kept retesting parts of my app that I knew would work, and then avoiding the part of my app that I was afraid was broken.
As you’ve probably guessed, when I submitted my little web app for grading, the company I was applying to immediately found a bug that occurs when a user changes their username, and then tries to log in again with the new username. Somehow, I had managed to pat myself on the back about my application while simultaneously not testing a likely point of failure. I’m happy with the job I ended up at, actually very happy, but I think there’s an important lesson here:
Even though I thought I was doing my best, my testing was self-congratulatory rather than dispassionate. I should have been trying to get my app to malfunction, not trying to remind myself that the code I wrote did what I wanted. I was, in some way, voluntarily blind to a point of failure. It’s a mistake I hope not to make again. I think one countermeasure against this sort of voluntary blindness is to ask yourself, not “Is my app tested?” but “If I were trying to crash this app, what would I do? Invalid inputs? Too many requests? Telling it to open a file and then deleting the file while it was still working?” In short, I recommend that you do terrible things to your code.
I missed out on an offer because I was focused on what could go right with my web app, and I should have been focused on what could go wrong.
Anyway, I hope this post will keep you from repeating my mistakes.
Till next time, happy learning!