The ultimate goal of technical interviews is determining how candidates will perform in your specific work environment. Arguably, one of the best ways to do this is through a paid contract involving real project tasks to be completed in a few nights or a weekend; however, this setup is not always feasible.
Even though the typical technical interview is not ideal, it is sometimes necessary. In my experience — on both sides of the interview table — the logic puzzles, pen and paper coding, and random algorithm quizzes tend to screen for candidates who are good at interviewing rather than assessing desirable traits, such as:
- Solid grasp of programming fundamentals
- Capable of applying existing knowledge in new ways
- Willing to tackle problems outside one’s experience
From many years of doing technical interviews, one test has consistently identified candidates that proved to be an excellent addition to the team: the “Foreign Code Test”. Candidates are presented with a simple program in a language they do not know, given a thorough description of what the code does, and asked to make modifications to the logic. If you think that this is exactly like all the other “gotcha” interview techniques, completely detached from what an actual job will demand, please bear with me; I promise that this exercise hits on practical skills that a good developer will have.
First, some ground rules:
Choose the proper language - pick something they have not worked with before but is not completely alien to them — e.g. if the candidate knows PHP, Haskell is probably a poor choice; try C# or, to offer more of a challenge, Ruby or Python.
Reassure the candidate - acknowledge up front that they don’t know the language and assure them that it is not a “gotcha” or trick test; you want them to succeed. Interviews should be collaborative rather than adversarial so this is an extremely important point!
Provide resources - either be available to provide guidance or allow them to search online for useful documentation and articles.
Provide required concepts - the provided code should demonstrate all the concepts required to accomplish the requested changes — e.g. do not expect a candidate to write a loop if a looping structure does not already exist in the code.
Provide background - there should be a full description of what the code does. It should also include full comments but, if you wish to make it more challenging, don’t.
Compile, run, and debug - allow the candidate to compile, run, and debug their code. Coding in a vacuum sucks; getting feedback from the compiler or interpreter is important.
By following the above guidelines, this test can reveal important traits about candidates:
- Were they hesitant to operate outside their experience or did they embrace the challenge?
- Did they ask questions first or dive right in?
- Can they process, assimilate, and apply new concepts?
- Did they establish a complete high-level understanding of the program despite being unfamiliar with the details?
Consider the following program in Ruby:
# This program picks a random number and then asks the user to repeatedly guess it
# by entering a number until either the number is guessed or the user enters a blank.
# If the user enters "help", the random number is displayed.
# Pick a random number.
rand_num = rand(100) + 1
# Initialize guess
guess = ''
puts 'Try to guess the number (hint: it\'s between 1 - 100)!'
while guess.to_i != rand_num
if guess != '' && guess != 'help'
puts 'Nope, not it.'
end
print 'Guess: '
guess = gets.chomp
if guess == ''
puts 'Done guessing? OK, bye...'
exit(0)
elsif guess == 'help'
puts "The number is: #{rand_num}"
else
puts 'Checking...'
end
end
puts 'You guessed it!'
…and some modifications to make:
- Tell the user if a guess is low or high
- Check if the guess is outside the range and warn the user if it is
- Change the allowed range of
1 - 100
to25 - 250
Notice that the above code and requested modifications:
- Describe everything the code does
- Include all syntax and concepts needed to implement the changes
- Is brief and straightforward with no “clever” code
- Does not require any specific algorithm knowledge to complete
Here is an example of what to expect from a good candidate:
# Pick a random number.
rand_num = rand(250 - 25) + 25 + 1
# Initialize guess
guess = ''
puts 'Try to guess the number (hint: it\'s between 25 - 250)!'
while guess.to_i != rand_num
if guess != '' && guess != 'help'
if guess.to_i < 25
puts 'Number must be no less than 25'
elsif guess.to_i > 250
puts 'Number must be no more than 250'
elsif guess.to_i < rand_num
puts 'Nope. Higher!'
else
puts 'Nope. Lower!'
end
end
print 'Guess: '
guess = gets.chomp
if guess == ''
puts 'Done guessing? OK, bye...'
exit(0)
elsif guess == 'help'
puts "The number is: #{rand_num}"
else
puts 'Checking...'
end
end
puts 'You guessed it!'
It runs and it implements the requested changes. Could it have been refactored? Sure but that misses the point. Remember, this person is unfamiliar with the language and all its features yet they were able to parse the code, map it to the described behavior, and apply that knowledge in order to implement the requested changes.
More advanced candidates might even go a little further, pulling out the magic numbers 25
and 250
and consolidating the guess checking:
# Pick a random number.
min_num = 25
max_num = 250
rand_num = rand(max_num - min_num) + min_num + 1
# Initialize guess
guess = ''
puts "Try to guess the number (hint: it\'s between #{min_num} - #{max_num})!"
while guess.to_i != rand_num
if guess != ''
if guess == 'help'
puts "The number is: #{rand_num}"
elsif guess.to_i < min_num
puts "Number must be no less than #{min_num}"
elsif guess.to_i > max_num
puts "Number must be no more than #{max_num}"
elsif guess.to_i < rand_num
puts 'Nope. Higher!'
else
puts 'Nope. Lower!'
end
end
print 'Guess: '
guess = gets.chomp
if guess == ''
puts 'Done guessing? OK, bye...'
exit(0)
else
puts 'Checking...'
end
end
puts 'You guessed it!'
Regardless of how a candidate does, it is important to review the results with the candidate, understand their thought process, and discuss any stumbling blocks. Find out if they have a sense of what could be improved but are unsure of the proper syntax or language features to implement it. See if they have any insightful observations or questions about the code or the language.
This approach is not foolproof and will not be a fit for all hiring situations (e.g. interns or Jr devs may not yet have the experience and skillset but if they can handle it, hire them on the spot!) Will this filter out potentially good candidates? Possibly but the number of bad candidates this may filter out is enough to be worth the risk of missing a good one.