Thank you to Niko Roberts, Dwayne Charrington, Gary Donovan for suggesting this topic.
This is Part 2 of my series on hiring in tech, in which I discuss some hot-button issues and controversies in the software engineering hiring process specifically. Don’t care about hiring software engineers? You can probably skip this one.
In Part 1 I provided a few general tips for how to think about, design, and conduct an interview process for tech roles more generally. Although you can read this article on its own, I strongly recommend reading Part 1 first as it provides valuable context.
The Great Algorithms Debate
Let’s get this one out of the way.
Algorithm-based engineering interviews have been made famous by employers like Google and Facebook. Whether to emulate that tends to be an emotive topic.
On the one hand, we have a view that can be summarised as follows:
It is ridiculous to test somebody on their ability to do red-black tree insertion when their day job mostly involves building React components.
On the other hand there is the following view:
Algorithms and data structures are foundational to good software development and testing these abilities is predictive of whether somebody is a good programmer.
I lean towards the latter position: that algorithmic thinking is fundamental to a software engineer’s craft. Furthermore, anecdotally I have reason to believe that solid algorithmic skills correlate quite strongly with a person’s overall skills as a software engineer. Therefore, I am in favour of having one interview that is focused on algorithmic skills.
However, that doesn’t mean that it makes sense to expect your candidate to battle their way through a bunch of esoteric tree manipulation or advanced sorting or dynamic programming or whatever. When I ask algorithmic questions, I tend towards the easier end of the spectrum. But I do then expect the candidate to be able to reason in a clear way about the problem and produce credible code implementing their solution.
Here’s what a good candidate should be able to do with an algorithmic problem:
Understand what is being asked of them, and be able to ask clarifying questions.
Explicitly state any assumptions they are making.
Express their thinking out loud.
Converge towards and explain a working algorithm.
Consider edge cases.
Have a basic understanding of efficiency/algorithmic complexity. Big-O notation is nice to have, but what we’re looking for here is that they understand the difference between something scalable and unscalable.
Express their algorithm as clean, clear code. It doesn’t need to compile, but it has to be more than pseudo-code.
What do I consider to be an “easy-ish” algorithmic question? Here are some examples:
Detect whether a string is a palindrome.
Keep track of the five largest numbers in an unordered list.
Given an integer, return its binary representation.
Create a basic inverted index structure from a string of words.
These sorts of questions are simple enough that they don’t require deep CS experience, but are nuanced enough for a strong candidate to be able to show off a little.
Generalist vs. Specialist
Another difficult topic is that of balancing generalist software engineering skills against more specialised skills. Imagine you’re building a Gatsby application and are looking to add an engineer to a feature team. Do you advertise for a software engineer? A frontend engineer? A React engineer? A Gatsby engineer? And once hired, will the organisation treat them as a software engineer or as a Gatsby engineer?
The answer is context-dependent and nuanced, but I do have a heuristic: aim for generalists unless you have a specific need for a specialist.
There are two reasons why I am biased towards generalist software engineering. The first is pragmatic: within an organisation, the more generalist the orientation of your engineers, the more flexible the organisation is. Imagine you decide to migrate your app from Gatsby to Next.js. Do you need to replace all your current Gatsby devs? If faced with that decision, you will probably just decide to stick with Gatsby… even if that is not otherwise the optimal decision. The state of the art is constantly shifting, as are the needs of the business. Having engineers who view their roles and career aspirations more broadly allows you to deploy them on tools and stacks that are the best fit for the needs of your business.
The second reason is that it is my observation and experience that viewing oneself as a generalist software engineer correlates with being a better engineer overall. My belief here is that a software engineer’s skills in a particular context benefit from having broader knowledge and experience across contexts. A React engineer becomes a better React engineer by understanding how Angular works; a backend engineer becomes a better backend engineer by understanding the concerns of the frontend applications that consume their APIs.
There are of course times when a specialist is just what you need. For example, if you’re building a complex stack on top of Kafka, it’s probably worth having someone on the team with significant Kafka experience. They’ll know where all the bodies are buried. Another time you want a specialist is when speed is of the essence. If you’re an early stage startup trying to get to market ASAP with a Rails backend, significant time will be saved by bringing in an experienced Rails specialist.
There is more to be said… perhaps this should have been a topic all on its own. From a hiring point of view, though, the important thing to do is to make the generalist vs. specialist choice deliberately and carefully (see “Be Clear What You’re Looking For” from Part 1), and to make sure that this choice flows through to the entire process. That means that everything from the job description through to the interview rubric should be formulated with this choice in mind.
Many companies have the desire to have a “technical screener” stage to the hiring process: some way of filtering candidates before inviting them to a full onsite (or remote equivalent).
I have seen three main types of screener:
The phone screen
The take-home challenge
The online coding test
It is worth noting that many candidates detest the screener phase, especially if you opt for a take-home challenge or online test. At the extreme, especially in the current buyer’s market, that means that some candidates will simply opt out of your hiring process. Nonetheless, screeners do serve a valuable function for companies who are trying to make sure that their engineers’ valuable time is only spent on candidates who have a decent chance of making it through the process.
What you have here is a classic tradeoff between candidate-friendliness and the efficiency of the process. You should make a decision that suits the circumstances your organisation finds itself in. In a talent-scarce market and if your employer brand is not strong, you probably want to avoid pissing off a single candidate. On the other hand if you have plenty of decent applicants for relatively few positions, you will need a way of deciding who to move forward with and minimise time spent on unviable candidates. For example Google cannot possibly put every applicant who looks good on paper through the full interview process.
Having said that, if you do go ahead with a screener you must do everything you can to respect the candidate’s time and skills. That means:
Make sure the time investment from the candidate is modest. Take-home challenges, I’m looking at you! Making somebody invest 12 hours on a challenge is not OK.
Keep communications up and turn things around quickly. It is incredibly frustrating to invest your unpaid time in a process only to have the recruiter go quiet or for it to take ages for a decision to be made.
If it’s a “no”, provide feedback. The candidate has invested time and effort, make it so there’s something in it for them. That way it’s at least a learning opportunity.
Software engineers are often stereotyped as giant nerds who can see the girl in the red dress by staring at a wall of code, but have trouble stringing a sentence together or making eye contact.
Like all stereotypes, there is a kernel of truth there. People like that exist in the profession. However, they are not likely to be high performers within an organisational context.
Building a software product is actually a massively collaboratively undertaking. While so-called “hard” technical skills are critical to building robust software, the “soft” skills---expressing complex ideas clearly, listening well, understanding customer and business needs, negotiating and co-operating with others---are just as, if not more, important.
That means that testing for communication and collaboration skills should be an explicit part of your software engineer hiring process. In Part 1 we talked about having rubrics; communication skills should be listed as part of the assessment rubric for at least one of the interviews in the hiring process.
Make sure you don’t hire a savant. Building software is a complex team activity and you need folks who can work well with others.
Did you Find this Valuable?
I hope you enjoyed Part 2 of this series on tech hiring. Next week I will share Part 3, in which I talk through my suggested engineering hiring process.
If you are getting value out of People Engineering, I have a small favour to ask you: please think of one person you know who may enjoy the newsletter and share it with them right now.
How is easy that? You’re already here! Think of someone, and share it with them using this button:
Boom, done! Thanks so much for your support.
Thank you so much for these two super useful articles Yaniv!