Wednesday 8th December 2021, 21:55PM
Algorithmic-style questions (also known by the genericized name of LeetCode and HackerRank) have become an industry standard of technical tests for software engineering roles, thanks to FAANG (well, MANGA) companies popularizing them for the past decade. However, go to any online community of software engineers and you won't have any difficulty in finding complaints about them. They're too hard, they're unrealistic, they're irrelevant to the actual job are all common complaints, and one might be tempted to think this is a standard case of rejects collectively whining the loudest. But I don't think it's just that (and presumably neither do you, if you're reading this) - not only are the criticisms logically valid, but it's also not too difficult to find stories of hiring managers who end up hiring candidates who perform well in coding tests but are in the end ultimately not very good at their job.
Before I get into the meat of what I think could be better, it's important to realize that there is some value in AQs.
On the other hand, the flaws are obvious:
The problems are clear, but what would a better solution look like? Well, for starters, I think it's important to contextualize the goals of what you want to hire for. If all that's needed is a pure HTML/CSS code monkey, then you can probably just give them a relevant take-home task. But in many cases, if you want to hire a smart, adaptable and well-rounded software engineer that will play a crucial role in shaping out the tech of your company for years to come, then you're going to have a finer criterion. The following might be an example:
Notably, AQs only assess the first point, maybe the second one, and arguably neither to their fullest extent. The third point is often assessed pretty easily with a couple of questions ("What's the difference between client side rendering and server side rendering?", "What's the advantage of docker/kubernetes compared to VMs?", etc) either at the end of or in a separate interview, so our coding question won't need to concern itself with that. The fourth point is usually covered best, in my experience, via a conversational pair programming method. Note that when I say pair programming, I absolutely do mean pair programming. Not the interviewer staring at you awkwardly as you struggle on, occasionally giving one or two hints in disappointment. Actual pair programming, where they treat you as a coworker working towards the same goal. I find it pretty obvious that the best way of seeing what it's like to work with someone, is to work with them on a problem. I think the main reason this isn't done more with AQs is that they are so one-dimensional that the answer would be given away.
Something else I constantly have to remind myself (and my peers) is that interview processes are not necessarily designed to maximize true positives, but instead to minize false positives. What that means, is that companies aren't directly looking to hire the best person for the role, but rather to reduce their chances of hiring someone who's bad for the role. After all, it makes sense that a bad hire is probably worse than missing out on the absolute best candidate. That's why there's so many damn interview stages that act as straight-upo filters rather than differentiators of varying levels of excellence.
Another important factor too often ignored is that interviews are a two-way street (or at least, they really should be). When interviewing for a company, in my head I'm also asking the following questions:
The best interviews I've had have ticked all three and left me with a feeling of excitement and actually really wanting to work there. The worst interviews have left me feeling used and empty like nothing more than a cog in their recruitment wheel.
With all the above in mind, perhaps we can get cracking now. In software engineering, "scalability" is often talked about a lot, in the sense that code should be able to be easily adapted and modified as requirements change. I think we can apply the same concept here, in trying to find a question that can be used in a variety of settings and seniority levels. Here's one such premise that I thought of at my last job (and would have used it in interviews had I stayed longer):
You're building a platform that allows users to have (multiple) pictures in their profile. How would you design/write code that allows users to add, remove and change their pictures?
Note that this is the premise of the question, and is still a little bit vague. I wouldn't expect a candidate (particularly junior ones) to be in a position to get started right away from those 2 sentences alone, but this is where the important details and context come in. Say, you're interviewing a junior who may not have a lot of experience (particularly with specific libraries/frameworks), then you can frame it a little more specifically:
Write a class ProfileImagesEditor, that takes in an array of image URLs (represented as strings) in its constructor representing the current user's photos. Write methods for that class that represent adding, deleting, and replacing images. Lastly, write two additional methods - one for previewing the new images, and one for getting all the final changes made.
And then provide some code examples...
// Example
const editor = new ProfileImagesEditor(["A", "B", "C"]);
editor.delete("A"); // Should result in a preview() of [ "B", "C" ]
editor.replace("B", "D"); // Should result in a preview() of [ "D", "C" ]
editor.add("E"); // Should result in a preview() of [ "D", "C", "E" ]
Another good way to explain the above is to mention that this is pretty much the functionality of changing one's photos on Tinder - you can make changes and preview them but they won't commit until you click save on the entire thing.
Note that there's still a little vagueness (which may be a good opportunity to see the candidate's ability to ask good questions), but you could do the following variations on the same premise:
You can probably think of more ways to add twists to this question, but more importantly, you should be able to see the positives of this approach:
I'm not saying that it doesn't come without negatives, though. For one, this relies on the interviewer being sociable and making the interviewee comfortable enough to pair program with them constructively - especially if you want to do it in an open-ended way. And for another, some candidates will simply be too used to AQs and struggle to perform well in this format. It also doesn't directly test a candidate's ability to write code with good complexity. But for the most part, I do think this is a strictly better way of assessing a candidate's coding (and other) abilities than LeetCode.
Whilst the example I've given above is pretty clear, I appreciate it's not for everyone. Fundamentally, not all software development roles require being able to tackle open-ended challenges and having to make big design choices. This approach isn't aimed at software houses that churn our CRUD applications or do web development consultancy, and that's okay. If you don't think what I've outlined above is appropriate for your needs, then again that's okay - it would be foolish to think there is a one size fits all approach anyways.
I'm not an expert on hiring and am certainly not arrogant enough to think I've solved the industry's problems in one blog post - just merely posting my thoughts on what I think a good process is in the hopes that it'll have a good impact somewhere someday. Whatever your thoughts are, I'd love to hear them either in the comments or via contacting me directly here.
If you enjoy the above article, please do leave a comment! It lets me know that people out there appreciate my content, and inspires me to write more. Of course, if you really, really enjoy it and want to go the extra mile to support me, then consider sponsoring me on GitHub or buying me a coffee!