Do you remember preparing for your last interview? You might have bought one of the books on interviewing, or spent time practicing on sites like HackerRank or LeetCode. Perhaps you read one of the many articles on “The 13 most popular React.js interview questions!”. What was your interview experience like? Was it engaging and fun, or frustrating and disheartening? I certainly have memories of interviews on both ends of the spectrum.
What about the last time you were interviewing for a position on your team? How much prep work did you do? If you were anything like me, you’d start reviewing the resume and looking for a question about 15 minutes before the interview started.
Interviews seem like a burden. They’re a distraction from whatever you’re currently working on, but the outcome of the interview is just as important to you as it is to the person you are interviewing. The decisions you make during and after the interview will affect your work life for the next few years. Get it right, and you have a wonderful new team member, someone you love to work with.
With so much at stake, there’s surprisingly little information available for the people who are giving the interviews. I thought I’d share my thoughts on the subject. Hopefully, some people might find it useful.
Know why you are asking the question
Why do we ask technical interview questions? Think about the sorts of things you want to know about a candidate. Can you code? Do you have good debugging skills? Do you have good problem-solving skills? Unfortunately, you won’t get very far by asking these questions directly. Interviewing would be so much simpler if you could!
Instead, you need to go after the answers indirectly. You do this by asking the candidate to perform some task and then observe their behavior. That is the function of the technical interview question. It’s just an excuse to get the candidate to perform a task you can observe.
With this in mind, it’s important to know what qualities you are looking for before picking a question. You can then evaluate any given question based on how it might give you insight into those qualities. For example, let’s say you want to evaluate the candidate’s design skills. You might ask a question like this:
I have a Vehicle base class with these functions: make(), model(), weight(), hasTowHook(), canPlugIn(), hornSound(). Possible types of vehicles might include a sedan (Toyota Camry), a pickup (Ford F150), or an EV (Chevy Bolt). Design me a class hierarchy that represents these different models.
There are a couple of issues with this question, but the biggest one is that it doesn’t meet our requirements. It might be an adequate test of basic polymorphism, but it’s not complicated enough to get a good sense of a candidate’s design skills. A better question might be:
You're building a web UI for commercial property owners to manage their security cameras. Each camera has some properties (make, model, location, orientation, etc…). You'll also need to keep track of other objects, like users, permissions, buildings, recordings, etc. The application needs to be able to export a backup file. This file needs to be readable by newer versions of the application. Design a system to take all the cameras and related data, and write that file.
This is a much better question for evaluating design skills. First, the problem is more realistic. There is a lot of detail to be considered. What data format do you use? How do the objects relate to each other? How do you handle versioning and compatibility? Do you care about making the file easy to read, or making the size of the file small? There are many, many valid solutions to this problem. Exploring the possibilities with a candidate will give you a lot of insight into how they think.
If all you learn from a question is how many hours a candidate has spent on HackeRank, then perhaps it’s time to find another question.
The question should be relevant to the work the candidate will be doing
If the person you are interviewing gets through the interview and accepts the offer, you’ll be working with them five days a week for the next few years. You need to make sure they are comfortable doing the day-to-day work that makes up the bulk of software development.
If that’s the case, why do we so often ask about obscure topics during an interview? We try to asses whether a candidate has a strong background in computer science when in practice, it has very little relation to real software development. If you ask about theoretical topics, you’ll get a sense of the candidate’s background. If you ask practical questions that resemble the work you do every day, you’ll get a sense of what it’s like to actually work with the candidate.
Let’s look at a couple of example questions:
You are updating an existing REST request for your backend API when you notice that sometimes, the requests take a second or two to respond. You check your metrics dashboard and notice that your p90 latency looks good, but p99 is much higher than you expect. Where would you start your investigation?
If you’re a ruby shop looking for a backend engineer, this is a pretty good question. It’s quite likely that you’ve needed to debug a performance issue at some point in the recent past. Someone who is joining your team should be familiar with the process of debugging this kind of issue. On the other hand, not everyone has been exposed to latency percentiles. You would need to be prepared to explain the concept.
Now, let’s look at another question:
You are creating a new dictionary service, exposed to your users via a REST API. There are two requests. A POST request to add a new word to the dictionary and a GET request to get auto-complete suggestions when the user starts typing. Implement these two requests.
This one is a bit trickier. Depending on what you expect the answer to be, it could be a really great, useful question, or an irrelevant frustrating one. If you expect the candidate to take the words from the POST request, and add them to a database, then query that database with the GET request, then this is a great question. Building this sort of autocompleted search is a pretty common task for a Rails developer. There’s enough detail here to determine if the candidate is familiar working with databases, you can discuss the table structure, what indexes to use, and whether using something like ElasticSearch makes sense.
On the other hand, if you’re expected answer is to have the developer build a trie, and then use that for the auto-complete request, then you’re in trouble. If you were looking for an in-memory solution to the problem, a trie would be a great way to solve this particular problem, but tries are not a commonly used data structure. It’s unlikely that your average rails developer will ever need to use one. If a candidate fails to answer this question, have you really learned anything important?
There are good reasons for wanting to avoid databases in questions like this. You might be doing a coding phone screen, and adding a database might make the question too complex to implement quickly. In this case, implementing a simple in-memory solution is perfectly fine. When doing this though, stick with data structures that are commonly used in the work you do. For the vast majority of developers, this is limited to lists and hash tables. Depending on the language used, you might have a few different kinds of lists, and perhaps an ordered map. Queues are also a good choice. Other data structures commonly found in interview questions such as heaps, trees, and graphs are rarely encountered in the real world and should be avoided. If you can’t elegantly solve the problem without resorting to obscure data structures, then the problem is a poor choice.
If your candidates need to study for your interview, you are probably asking the wrong questions.
Make the question clear and easy to understand
Interviews are stressful! It can be hard to answer tricky technical questions when under pressure. Have mercy on the person you’re interviewing and spend some time making sure your question is clear. Not only will they appreciate it, but you’ll have a much better chance of getting a useful answer.
How do you know if your question is clear? Test it! We test our code, why not do the same for our interview questions? Ask a teammate the question and see how they do with it. This is great for two reasons. They’ll usually be honest with you and let you know what they think, and now you have a baseline to use when you ask the question in a real interview. Once you’ve done this a few times, you’ll start to get a feel for the process.
Friends don’t let friends ask buggy interview questions.
Leave room for side conversations
Some of the best interviews I’ve been involved in are ones where the conversation veered off track into an interesting side topic. For example, in a recent interview, I asked a candidate how to make a piece of code he’d just written thread-safe. The obvious answer would have been to add a mutex. Instead of giving the answer I expected, he pointed out that if I cared at all about the performance of the code, it should never be run from more than one thread. We then got into a conversation about how modern multi-core CPUs handle caching, and we discussed various methods of getting data in and out of the thread running the code efficiently.
This wasn’t the answer I expected. Instead, I got a great conversation that gave me a lot more insight into how the candidate thought. It was also a great opportunity to have a conversation outside the formal bounds of an interview question.
If you get an answer you didn’t expect, dig a little deeper.
I hope this post has given you some things to think about the next time you’re giving an interview. If nothing else, don’t pick the first acceptable looking interview question you find 15 minutes before the interview starts. Take a little time to think it through. Test the question with a colleague. The person you are interviewing will appreciate the effort.