What teams are looking for isn’t mysterious. Here’s how to land the job.
I’ve been a hiring manager for over 10 years, helping teams design their interview process and vet candidates. I’ve also conducted countless technical interviews. Time and again, I’ve seen promising candidates undermine their own potential by stressing out too much about their own perceived technical weaknesses and neglecting to ground themselves in the two biggest factors in the decision to add a new person to the team. If the interview is well-designed (and many aren’t — *cough* whiteboard brainteasers *cough*), it should show off skills you’ll be using every day in your job. In my experience, the most valuable of these are: 1) communication and 2) problem solving skills.
That’s not to say that data structures and algorithms aren’t important. It certainly helps when new teammates show up with production-ready skills. However, being an engineer means constantly learning new things, no matter what level you’re at. I would much rather hire a junior candidate with strong learning and communication skills than a senior developer who thinks they know all they ever need to know.
Surprisingly, I’ve seen far too many candidates fail to demonstrate value as a teammate by making some common unforced errors. Let’s take a look at a few of them:
It’s likely that one or more parts of the assignment you’ve been given aren’t clear to you, or you aren’t familiar with a term that’s being used. That’s ok! I don’t expect every candidate to know everything, and there’s a chance my instructions could be improved. It doesn’t hurt to ask clarifying questions about the assignment, or even supportive questions like “Am I on the right track?” Checking in with the interviewer regularly shows that you’re interested in gathering adequate information, validating your assumptions, and correcting course if necessary.
The coding exercises I’ve given have shied away from the standard brain-teaser problems that only serve to intimidate. Instead, I prefer to give explicit instructions for how to do well. I even give the exact expected output I’m looking for. Yet a majority of the time, candidates fail to check their work to make sure they’ve fulfilled all the requirements before declaring it “done”. Little sloppy mistakes in the output — when the exact, verbatim expected output is given to you — indicate the candidate hasn’t clearly understood the problem and is building something based on an misconception they may have in their head, not the actual requirements at hand. This sort of cognitive bias problem comes up all the time on professional teams, so it’s important to get good at spotting it. Before you declare it done, make sure you’ve run your tests, run your build, and double-checked your output. Evaluate your work as though you’re somebody else who has to pick up unfamiliar code. Perhaps consider giving your own instructions to make it as simple as possible for someone else to get started with what you’ve written.
A large portion of an engineering job is spent not writing the application code, but doing other important tasks: Gathering requirements. Breaking down stories. Writing tests. Testing manually. Talking through problems with your teammates. Code reviews. Retrospectives. Posting cat gifs to slack. All of these activities ensure the code actually written is doing exactly what it should be doing, and help to ensure the team is on the right track. So I want to see a candidate who can approach a problem with a plan, not someone who is going to dive headlong into a mess of spaghetti code.
Once you have a plan, a great place to start coding is not in the app code itself, but in the “checking” code, which might be tests (you are writing tests, right?) or types. Writing tests to verify behavior will ensure your implementation behaves correctly. Declaring the data structures you’re working with will ensure your implementation is guided by that structure. The famous quote still rings true:
“Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.” — Fred Brooks
Of course, your design needn’t be perfect. You will undoubtedly learn new things along the way. Which brings us to:
A smooth workflow involves little cycles that resemble the Scientific Method:
Yet too often, nervous or inexperienced candidates can get caught up spending all their time in step 2. If you don’t have a solid goal in mind or plan for achieving it, you’ll quickly find yourself with several half-finished changes and your code in an un-runnable state. When you’re trying to achieve too many things at once, it becomes more difficult to finish any of them.
As with any new feature you write, it’s important to minimize the time the code spends in an un-runnable state so you don’t block yourself from being able to try things out. That usually boils down to finishing one thing before starting the next. You’ll be able to learn from each experiment, which will help confirm you’re on the right track.
And if you do get stuck, it’s ok. Just take a breath and return to step 1: Restate what you’re trying to accomplish.
None of this is to say you shouldn’t also study your data structures & algorithms, practice whiteboard interviewing, and spend time beefing up your technical bonafides. But it’s important to remember when you get stuck — and you will get stuck, especially if you’re nervous (and there’s nothing wrong with that) — to get back to the fundamentals of problem solving and communication: the basic tools you can rely on to get you un-stuck.