For as long as I can remember, there’s been a disconnect between kinds of stuff people ask in software engineering interviews and the day-to-day work that software engineers do. As a recruiter and a former engineer, this disconnect is particularly salient because when I evaluate candidates I have to ask myself two separate questions:
- Will this person be able to pass a few rounds of coding interviews?
- Is this person actually good?
It’s a bit funny that whether the person is good is somewhat immaterial if he isn’t going to make it past the CS fundamentals gauntlet. That said, I think that the standard interview process isn’t the worst predictor of success on the job — people who are good at solving toy problems, have solid knowledge of various data structures, and for whom evaluating code efficiency is second nature also tend to be good at being engineers. This is perhaps a classic correlation vs. causation problem — people who are good at being professional coders also tend to be good at being interviewed. However, I’m not sure that they are good coders entirely because they are good interviewees. In other words, I would guess that this approach has a pretty high false negative rate. Unfortunately, I don’t have a good solution to this problem, and surely lots of false negatives is better for a company than the same number of false positives (especially if the company has a good brand among engineers that affords it a revolving door of applicants).
Recently, someone on Quora asked about what CS concepts are actually used on the job (as opposed to what candidates are expected to bring to the table). Bulat Bochkariov did an amazing job at attacking both this question and discussing coding interviews. With his permission, I’ve reproduced his answer here.
Answer by Bulat Bochkariov:
The set of questions people ask is frustratingly disjoint from what’s important day-to-day. There are reasons, but I’ll try not to get sidetracked here.
Here’s a tiny list of things an engineer should be prepared for.
- It’s 2pm. The release gets cut at noon tomorrow. (Or we could delay, but that would suck kind of a lot.) This piece of code is running way too slow for us to ship it with our names on it. How would you decide what to do? And then how would you do it? Remember that there’s still that other feature we were working on.
- We need to do X. You know our stack and our toolchain. Research the options, then determine the next step and take it.
- MySQL is seriously melting with this growth. We can’t keep doing all these joins.
- There’s a critical bug in production.
- We’re losing velocity. Our crufty code is keeping us from making changes quickly. What’s the root of the problem? What would really good abstractions look like? What are we trying to do? And how do we keep doing it while cleaning up this mess?
- EventMachine is leaking more than normal.
- Someone took out Git. There’s a crater.
- Is it ok not to encrypt this? Like, what’s the worst that could happen. Right?
- I think we’ve been hacked.
- We’ve got an interview today. They even mentioned some security experience. What do we ask? How? What will it tell us?
For the most part, no one cares if you can make a red-black tree. It’s not something you’ll be doing. It’s just a proxy for a few things that do matter: your ability to solve new problems and an understanding of the content in a core CS curriculum—or whether you can write code that compiles and runs. But those are just the basics. They’re necessary, but they’re not sufficient.
What’s more important is your understanding: whether you can see the forest for the trees and find your way to where you’re going. You don’t think in JavaScript or Python but in problems and solutions, on multiple dimensions at once. You know the details are important but they aren’t the point—except when they are, and you can tell the difference.
You don’t do stuff that’s clearly bad; consider that a given. You don’t leave O(n^2) code turds on the floor or weird recursion time bombs that will blow the stack if n gets bigger than a thousand. But in a Maslow pyramid for programming, that stuff is on the bottom steps. It’s important to keep reaching for the top.
The most important question you can ask is “why.” What problem does this project solve, and what problems is it made of? Why should I consider Factor A over Consequence B? Why the hell is there a ServletBeanAdapter here? And keep in mind that sometimes it’s because an engineer took time to fully understand the problem, examined the upside, noted the risk to his or her own timetable, considered the security concerns, thought about maintainability, sketched out some more powerful solutions, decided not to waste the effort here, and made a quick decision that looked right when faced with finite time and lots of ambiguity. That’s what software engineering is about. You develop judgment and you learn from your mistakes.
And that’s what no one asks about.
Here’s where I should say a couple things. First: I’m a “new grad,” which means I’ve interviewed enough that I can’t count them on my fingers and toes, but I wouldn’t need to grow a lot of extra hands. That leaves me biased in a number of ways. Second: The context is important. If you work on machine learning, you’ll definitely need some statistics. For distributed systems, you’ll need data structures and concurrency. I don’t mean to say that core CS is not important. I’m talking here in generalities, so please don’t take them for specifics.
In my experience, what people ask is more like this.
- FizzBuzz variants; easy looping questions. (Because it would be rude to check your pulse.)
- Counting nodes or levels in some sort of tree. The goal is usually to see if you can think recursively or how you’ll try to hack the problem if you don’t. I love to harp on these, but honestly they make pretty good screens.
- Basic questions from an algorithms class. Can you solve a searching problem if you aren’t told how? Can you mentally connect the properties of BFS with level-order printing in a binary tree?
- Data structure questions with a fairly clear right answer. Given some data and a time or space constraint, can you process it a certain way? Can you make a stack with constant-time maxValue()? What structures would you hook together for an LRU cache? A lot of these are just fill-in-the-blank if you know the standard structures’ time and space costs, but that’s already showing that you know something worth knowing.
- Sometimes they’re just random made-up problems that you probably won’t guess in advance. Maybe some weird string questions or a twist on a dynamic programming problem. Some companies might ask more mathy stuff like rolling averages or random number generation.
And of course there’s plenty more. There’s a bunch of different lists online that people study with. I just don’t think what’s in them is the point. The most important thing I have to share, strictly true or not, is that the skills you’ll need for interviews are not the skills you’ll need at work.
If you’re interviewing, brush up on your textbook knowledge. Practice your dynamic programming. Go code up a union-find in C. Worry less about what skills you really need and more about the ones you need to demonstrate. They’re different. The standard problems people test you on are proxies for the things they really want. They just have a funny and imperfect way of finding out.