There has been a bit of noise recently on Twitter and on a few blogs about programming interviews
. The chatter comes at an interesting time for me since I've recently had an experience with the interview process at a major tech company.
I should stop and say that it's probably not typical for someone who is happily employed to publicly talk about pursuing another job opportunity. The way I see it, we all owe it to ourselves to occasionally gauge the market for our talents. When I worked for AT&T I always figured that I'd spend 30(+) years there and then retire. That's just what you did when you had a secure job with a big company. But things change. I left AT&T after 15 years and at the time I told myself that I'd always keep my options open in the future. So that's what I was doing recently when I applied for a job with Amazon.
The job I applied for was a virtual/remote opportunity. I've been working from home for 5+ years now. It has its ups and downs, but the "ups" far outweight the "downs" in my experience. I found the job posting online and figured "why the heck not" so I cleaned up my resume and applied.
I consider myself to be an above average developer - the kind of geek that considers it a hobby to use a Raspberry Pi with a remote web interface to automate and monitor his barn (more on that in a future blog post maybe). Do I consider myself "Amazon worthy"? I'm not sure, but I know that I love writing code and my performance reviews have always reflected the fact that I get things done. As a Tech Lead I've contribute to the success of some fairly decent sized web applications over the past few years.
A few days after I applied I received an email from a technical recruiter with Amazon. As I get older I tend to be more subdued in my reactions to most things, but I have to admit I got pretty excited at that first contact. The recruiter asked if we could talk about a different opportunity than the one I had applied for. I figured it couldn't hurt to get an interview on record with them so I said "sure, why not" and set up a call for the next day. That first call with the technical recruiter lasted about an hour. I won't mention her name, but I can't say enough good things about her. She helped me relax and was very easy to talk to and willing to help answer any questions that I had. She mentioned right away that the opportunity was on-site in Seattle and asked if I'd be open to relocating. I told her that it was something I'd consider.
As we wrapped up the call she started to tell me about the "next steps" in the process. She would talk to the hiring manager and they would then set up a "technical" interview with me. She noticed that I didn't have a formal CIS degree so she wanted to know how I'd felt answering some "technical" questions. A small doubt crept into my mind - as I'm sure is normal with most programmers who are self taught - but I quickly found some confidence. "How hard could these questions be," I thought? Certainly my 13 years of experience have prepared me for this.
Then she hit me with a few sample questions. The first few were easy.
Recruiter: "Do you have experience with multithreading?"
Me: "Sure, we often spawn long running processes into their own threads to improve the user experience."
A few other softballs came before things "got real" as they say:
Recruiter: "Can you explain the time complexity of a bubble sort?"
Me: "Ummm...Yeah, I'm not sure about that one."
At this point my face started getting warm and she started sounding like Charlie Brown's teacher:
Recruiter: "Something, something doubly linked list"
To her credit, she never made me feel like an idiot for stumbling on a few of those. It wasn't exactly a mentally exhausting hour - we had just talked about my experience and the projects I've been working on - but, after an hour it's hard to mentally switch in to that mode and I think she sensed that. At this point she proposed something that I never would have expected.
"Do you think if you took a little time to brush up on some of these topics that you'd be able to complete such an interview"
I told her that I would do my best to try and she offered to touch base in about a month or so. So now it was study time! After a bit of research I ordered a book that would supposedly prepare me for the process: Programming Interviews Exposed
When the book arrived I immediately started reading - eager to learn about merge sorts, binary trees and linked lists (oh, my!). All the good stuff
that the Super Programmers (TR) use! Then I realized why I hadn't learned about such things in the past - because they're mostly problems that have already been solved
. Most standard libraries already knows the most efficient sort to use for a list and when you call Array.sort() it uses that method. Linked lists? I've never used one, and maybe I never will. But the thing is - if I ever need
to use one, I'll most likely figure that out because I use a secret method that all good programmers use. It's tried and true, and I'm going to share it with you right now:
It's called Google
Shocking, I know. Thing is - most good (even great) programmers don't take the time to memorize every syntactical nuance of the languages and libraries they use, but they sure as heck know how to find a solution to a problem when they come across one. I hate to even mention it, because it may sound crazy, but there's almost a "gut instinct" that good programmers have. You may have had that feeling when you wrote a bit of particularly gnarly code to solve a problem. You thought "surely there must be a better solution than this." So you threw a TODO: in your code, or, better yet, you weren't bound by a ridiculous deadline so you took the time to find the "right way" to solve it.
As I read through the first 100 pages or so of that book I got hit with another sinking feeling. Most of the examples in the book used C or Java to show how a certain problem might be solved. Somewhere in those first few chapters it hit me: I've never really written Java code from scratch. I could code up a storm in Groovy - and I'm very familiar with the Java language itself, but if you pointed a gun at my head and told me to write a Java class from scratch in Notepad (or, even worse, on a whiteboard) I'm pretty sure I'd have to start saying my prayers.
But I'm OK with that. I love Groovy and I don't love writing boilerplate code like getters and setters when I can focus my time and effort creating an awesome user experience or writing some code to manage dynamic user forms. You know, the features that users give a crap about!
I've spent a lot of words here stating my case, but let's talk about some specifics now that really illustrate why technical programming interviews are worthless in their current form. How about the dreaded one (at least in my mind) - time complexity. A friend of mine shared this guide to Big O notation
with me when I told him about some of the questions I'd be asked. It's a handy guide, and the concept is solid, but at the end of the day it all comes down to good programming habits in my mind. If I'm trying to find an item in a list, and it's expected to be a reasonably short list, I'm going to loop over it until I find what I'm looking for. If it's going to be a bit larger and more time consuming, I'm going to Google how to do a binary search (divide and conquer). If I ever find myself writing a nested loop, well, the alarm bells better be going off in my head because now we're talking about some exponential complexity. Can I (or most programmers) break that down into O(n), O(log n), etc? No, they can't. But if they're writing applications for major clients that don't have serious performance issues then you should safely assume that they have a respect for what not
to do when it comes to operations that would be more complex than others.
Back to Java for a second. I love Java. I also hate Java. It's verbose. Groovy enhances the Java library in such a way that it makes hard things easier. As I read through some of the solutions to problems in the book that used Java I found myself getting angry. For example, on page 97 the book proposes the following problem:
Write a function that reverses the order of the words in a string. For example, your function should transform the string "Do or do not, there is no try." to "try. no is there not, do or Do". Assume that all the words are space delimited and tread punctuation the same as letters.
The book went on to solve this problem with 30 lines of C, but the Java solution would probably be pretty similar. If I needed to solve this problem in Groovy, it would look like this:
println "Do or do not, there is no try.".tokenize(' ').reverse().join(' ')
I'm not sure how it gets any easier than that. The people that wrote Groovy have solved these problems before - probably many times - and they realized that things like tokenize() and reverse() and helpful methods that make a programmers life easier. Would I be happy writing out 30 lines of code to solve that problem? Probably not. I'm not saying that I wouldn't do that if the job required me to, but you can be darn sure that I'd be selling a "better way" to the powers that be.
At the end of the day I turned down a further interview with Amazon when the recruiter touched base a month later. I don't regret turning it down. I've talked to some friends that have gone through these types of technical interviews and they all end up saying the same thing. Essentially they are pointless tests of memorization of some low level standard library features and algorithms that you'll most likely never use on a daily basis. I get that they're trying to test your problem solving abilities and performance in a stressful situation, but there has to be a better way. Because the way it stands today these companies are missing out on some amazing talent. People that live and breath code - not new grads who got into programming because it's a growing, secure and well paying field.