browsing CV with magnifying glass

How to hire a developer: Part 4 – Why in-person technical interviews still matter

In the fourth and final part of his series, Mike Ritchie suggests that person-to-person interviews are still critical to hiring success, and explains how employers can nail this phase of recruitment.

There’s more to a technical interview than just the interview. Social interactions matter, and seeing your organisation and physical environment up close all matter to the candidate too. Both parties need to be able to gauge how this would work out for them.

I’ve been focused on technical selection for the last few posts, and you might have got the impression that everyone except developers is written out of the script. Not so: for in-person interviews, it’s rarely just 100% technical content.

Meeting the wider team and managers is important too, and HR/talent people have observational skills and a different perspective that gives vital balance.

I’m still going to be focusing on the technical selection, but that doesn’t mean that other things won’t happen on the day. Have a chat with your talent team if you haven’t already.

Preparation

Well before the interview, make sure both you and the candidate are clear about some key things.

If you want to run a pair programming session, you’ll need to decide whose device you want to run this on, and let them know in advance. If you want to work on some real code for your company, then your company policies will very likely place some restrictions on using the candidate’s equipment. I let candidates use their own kit if they prefer to.

Make sure you check whether the candidate has specific requirements that need you to make arrangements for them. Candidates might need some assistance for the day. Seek help and advice to make sure you’re getting it right for the candidate – don’t make assumptions.

Make sure the candidate has direct contact details for you, a mobile number especially. People sometimes get delayed through no fault of their own. Talk people through who they’ll be meeting and what to expect on the day. Make sure they’re comfortable with everything. Field any questions they might have.

And it sounds obvious, but when they arrive, do your best to put people at ease before you get into any technical interview. Chat, be friendly and open, let them know it’s going to be informal. I’ve heard of a number of companies where lunch with the team is part of the interview.

I love this idea, and I think the social setting helps a lot, but if you can’t stretch to lunch, at least create an opportunity for the candidate to meet other people in the team and have an informal chat.

Principles

Any interview format needs to be equitable. It’s about both you and the candidate being able to make an informed choice. Interview formats should reflect that, and you need to participate to let the candidate know what your company is like.

You should explore, and not just talk. If you can discover something about a candidate by solving a problem with them – in code, or any other way – do it that way in preference to pure discussion. Have discussions too, but explore ideas, code and design by actually doing things.

Keep some flexibility: you have a real, live human in front of you now, and a plan that’s too rigid won’t serve you well. You need to have some structure of course, but also keep some things fluid in what you explore in code.

Always solve problems in their native environment: if you want to have a discussion about code, write actual code rather than pseudocode. Don’t get the candidate drawing detailed UML diagrams, prefer to try things hands-on (sketching lightweight diagrams is perfectly reasonable as a secondary means of communication).

Formats that don’t work

Let’s deal briefly with a few ineffective formats that are still encountered:

  • 100% Technical Q&A: Nope. The whole dynamic is one-sided, and candidates end up guarded and nervous, in fear of that one question that they’ll blank on. There’s a place for questions as a way of filling in some gaps in the picture you have of the candidate, but it’s not something you should use as the main focus of an in-person interview.
  • Whiteboarding: Nope nope. Making a candidate solve code problems on a whiteboard in pseudocode is strange and anxiety-inducing. One exception: if you’re coding through a problem and both of you instinctively want to sketch something on a board – informal boxes and lines usually – fine, sketch away to supplement the code.
  • Experience-based CV discussion: Nope nope nope. Remember my point in Part 1 about formats that favour (over-) confident candidates who sell themselves well? Well, this format is what I was talking about. Experience is interesting though, and always a good discussion point for lulls and gaps, but don’t make it the core of the interview.
  • “Debug this paper listing”: Nope nope nope nope. I’m sometimes nostalgic for the 1980s, but mainly because I had hair, and not for the way that technical interviews were run. The instinct of good developers when confronted with unclear code should be to a) write characterisation tests and b) make naming and readability changes to make the code clearer. And you can’t do that on paper.

So don’t do any of these. Instead, get a sense of how someone would code in a collaborative setting by…wait for it…coding with them in a collaborative setting. I know, right? Who could have seen that coming?

Pair coding exercise

In my experience, this is the best way to get a balanced view of the candidate, their skills, their approach to code and problem-solving and how they’ll fit in a development team setting. I find that I can discover more about someone in five minutes working on a problem with them than I could in five hours of Q&A.

If you get this right, it becomes a focused discussion about code and tests and design. The coding problem you’re tackling is really a vehicle, not the destination. Honestly, this can even turn out to be fun.

Pick a problem that you feel will give you the best view of the candidate’s ability. This could be something technology-specific (web, android, iOS, embedded etc), or technology-agnostic challenge that doesn’t depend on frameworks and platforms. I think it’s better to pick something that’s closer to “real” for the role.

It’s fine if you want to use your own code, but try to pick something that’s not so specific to your organisation that it won’t make sense to an outsider. Be prepared to give people an overview and context of what they’re working on, and how it fits into your products or systems.

You’ll need to help if the candidate gets blocked, the same way you’d help in a team setting with a colleague. Good ways to keep things flowing are:

  • If you’re doing this test-driven, make a test list. I find it useful to do this with mini-stickies on the desk, because you can reorder things easily.
  • Try ping-pong pairing to get things moving, and to set the tone for an equal contribution. If you both want to change the pace to a driver/navigator style, this is fine.
  • Make suggestions if you sense that the candidate is hitting a wall. Help the candidate out. It serves no purpose to sit there watching someone get jammed up.

And what to look for as you’re doing this exercise? Let me tell you.

Development fluency

For a long time, I arrived at a gut feel view of someone’s abilities from pairing sessions. Over time, though, I was able to identify what this gut feel was really based on. There are five elements to a candidate’s fluency that I look for. If you take anything away from this whole series, I hope it’s these.

#1 Test-Driven

For the teams I’ve hired for, TDD has always been a desirable skill, so I look for it on CVs, and approach hands-on exercises this way. I find that it’s rare to encounter people are fully-formed TDD practitioners, even when it does appears on their CV…but I take it as a statement of intent, and an indication that people are bought into the idea and want to work on that skill.

Here’s what I’m looking for:

  • Working instinctively test-first, in the TDD microcycle, taking baby steps.
  • Understanding the value of tests for communication, naming tests to make intent clear.
  • Understanding clear layout of tests – “Arrange-Act-Assert” style.
  • Showing a decent level of proficiency with their test framework, good use of the right type of assertions and matchers, understanding how to pull out common setup and teardown.
#2 Clean, Crafted Code

This is where I’m looking for those Ethical Developer signs – someone who cares about code, about their users and their colleagues. Signs:

  • Using good names that express intent clearly.
  • Design as simply as possible with small, low-complexity, well-named methods.
  • Removing duplication.
  • Applying some TLC: formatting, layout and good whitespace form.
  • Good OO abstractions, cohesive, well-encapsulated types.
#3 Language

I look for people to be able to express design ideas well in their language of choice. This doesn’t mean I’m looking for stunt programming, or a deep knowledge of the dark corners of the language. It means doing simple things as simply and elegantly as possible for the target language:

  • A solid grasp of basics : types, control flow, scope, lifetime.
  • A decent grasp of the core language API. Not rote memorisation, but capabilities and major areas of functionality, and the programming model.
  • Core language features for executing OO design ideas – classes, interfaces, virtual functions and overriding, encapsulation, minimising mutability.
  • Mixing in functional idioms where they’re available and appropriate for the problem at hand.

The key point I look for here is that people use their language as a vehicle to arrive at clear, clean, readable code with good design, picking the language features and facilities to best achieve that.

#4 Tools

I look for people to use their tools effectively. And effective != “fast”. People need to be familiar with the core parts of their toolchain to work effectively, so a level of comfort with the editor/IDE, build system, and source control are all positive signs.

Examples of things that I like to see:

  • Refactoring code with the IDE/editor – especially rename and extract-method refactorings as a routine activity.
  • Formatting code consistently.
  • Knowing the build system, adding targets and steps to it.
  • Using source control effectively from IDE or command line.

I’m always super-happy to see a candidate use Git consistently during a pairing session. I always advise students to do this in technical interviews – it’s good for morale to know you can easily get back to a safe point if you get yourself into a jam.

#5 Collaboration

We want to have easy, rational discussions about technical ideas, and the direction we’re taking, and without ego intruding. We want to have everyone make a positive contribution, and we don’t want opinions and discussions to be suppressed by people who aren’t interested in hearing other viewpoints. Pairing is a great way to judge your candidates ability to work in a collaborative team setting.

Things to look for in your candidate pair partner:

  • Playing a full, active role, having ideas and opinions.
  • Being open to input and suggestions from you, actively listening, asking questions.
  • Being happy to switch over roles (driver/navigator) and to ping-pong pair.
  • Upbeat, positive and constructive about the coding challenge.

Bear in mind that for #1 to #5, you’ll need to calibrate your expectations based on the candidate’s experience level.

A better algorithms interview

The Silicon Valley tech giants see algorithms and algorithmic thinking as reliable predictors of job performance. These organisations hoover up Computer Science graduates from the posh end of the U.S. university league tables in huge numbers, and their major is directly applicable to most of the work they’ll end up doing.

But their hiring profile and their development focus may be very different from yours, perhaps almost unrecognisable. It’s a mistake to pick a technical interview format based on the assumption that because it works for Google or Apple, that it’ll work for you. It’s also a mistake to think that because it’s applicable for some development roles in your company, that it applies to all of them, at all experience levels.

Most discussions you’ll read online on this topic tend to have degenerated into a yes/no, good/bad argument, but that’s simplistic and unhelpful. There are a few aspects of this question that need to be teased apart: Whether, When, and How.

Whether: it’s sufficiently relevant to the role to make it central to the interview. And even if it is relevant, there’s another “whether” – whether it’s the best view you’ll get of the candidate’s skill.

When: if algorithm design or implementation is a significant part of the role, I recommend making it part of the face to face interview rather than an online screening test. The most challenging part of the process should be face to face.

How: good code generally comes from experimentation, and especially from collaborative experimentation. All of the characteristics I talked about above still apply if you’re working on an algorithms problem – there’s no “get out of jail free” card.

I take the view that an ability to reason is more important than an ability to remember, so create an environment – both technical and intellectual – where you can explore a problem. Write tests, measure performance and complexity, and discuss and act on the feedback.

Let’s take a typical algorithm interview example – finding the equilibrium index of an array of integers. I’ve picked this because it’s the sample test on Codility, so you can explore it there too and compare the tools and approaches. The goal is to find an index in the array where the sum of all the elements to the left of it is equal to the sum of all the elements to the right of it. For example, an array with the contents: {1, 2, 3, 42, 5, 1}, the fourth element in the array is an equilibrium index.

So I’m a candidate, and we have a first-cut implementation, my pair partner and I. It’s not great, we’re not especially proud of it, but small steps, right? We’ve written some tests too, and had good discussions about the edge cases. We can keep running these as we experiment with our algorithm.

And we have a framework that not only gives us benchmark timings, but also estimates the efficiency of our implementation. This works by pushing inputs of increasing size through our code, and then using the those timings to estimate the Big-O time complexity. Let’s run it. Ooh, is that the lights dimming as I hit <ENTER>?

hire a dev code view

Aye, O(n^2), not great – second line from the bottom on that output. But we talk it through, and we can see a better approach. We implement it, run the tests again to make sure we haven’t regressed. All good, so now we re-run the benchmarks:

Yay, O(n), what fun! Imagine the conversations we can have with a harness that lets us explore and experiment with our algorithm implementation! And also think how much more better this is for finding out how the candidate adapts to the results of these experiments.

It’s a world away from the online tests – we can run this benchmark as often as we need to, and it feeds into our discussion and changes in approach.

If you want to use this approach, invest some time in setting up a sample project specifically for interviews so that you can $ git clone and work on it easily. This benchmark framework is for C/C++ codebases and is Linux-specific. You’ll need to find something similar for your language and platforms, but it’s worth the effort. It’s greatly preferable to online tests. It’s an exploration, not an interrogation.

So…

If you have a role and a technical domain where there is a focus on algorithms – designing, implementing, optimising – then it’s perfectly valid for you to focus on this in your interview. You know your domain. You know what’s important.

But if the statement above doesn’t apply to your organisation or the role that you’re hiring for, don’t make it the default. It’s an option, but only one of many. Pick the problem that’ll give you the best view of a candidate in the time you have with them.

And if it’s both relevant and right for you, make it an exploratory process, not a test of memory.

Making your decision

It’s a good idea to keep some output to feed into your decision, as well as being good feedback for the candidate. Those five elements of fluency is a decent framework for that – have some notes on each. If it helps, you could have some sort of scoring framework for each item on there.

Get a view from everyone who’s been involved. If you’ve taken my advice and got a diverse pool of technical interviewers involved, this is the point where their voice really needs to count.

Give thorough and complete feedback to the candidate – if they’ve been in for an in-person interview, they deserve this, and they deserve it promptly. Ask them for feedback too – it’s important that you use candidate feedback to improve your approach.

Wrapping up

Well, this all turned out to be a lot more than I planned to say.

I hope you hire a great team. And I hope that team is creative, happy, mildly chaotic, diverse, human, talented, perplexing, compassionate, largely unmanageable, and endlessly surprising.

I built a team like that once, and it was the best I ever worked in. We’ve mostly moved on to other things, but I’m proud to call them my friends now.

Good luck.

Mike Ritchie is a developer and technical coach. He helps teams with hands-on development, and builds technical capability through coaching. You can find him on LinkedIn.

See also

To receive email alerts about more posts like this, sign up below

Let us help you make your next hire

Stay in the loop about upcoming employer events and hiring opportunities.

More

Find out more about becoming an employer partner with CodeClan.