Interviewing developers: To FizzBuzz or not to FizzBuzz

Photo by Maksim Romashkin on Pexels.com

I had held many interviews in the last years, and I never asked anyone to do a whiteboard coding or code something in the interview, nor I had anyone do screening with a hacker rank style platform. After the interview, what I occasionally do, if I consider it makes sense, I ask participants if they would like to do a small home assignment (usually something that should not take more than 30 minutes to an hour).

Before we get all worked up about anything, let me just say that interviewing and recruiting are incredibly complex topics, and the following post is more of a brain dump.

Now that you are a bit familiar with my modus operandi, we can start unpacking this for the reasons why I think this leads to the best outcomes with mid to senior-level positions for business-oriented software. 

First and foremost, let’s address the elephant in the room, the question of what I think or why I think there is a problem with this kind of practice.

But first, a story

If you are a reader of this blog, you should be expecting this, there is no getting around stories, I mean, this is written so you could skim or jump over it, but I think this is quite important to the whole narrative.

Some time ago, 2 -3 years I think, I came across this cool and nifty platform called codingame.com, and I randomly picked this nice little challenge.

Quote: “The goal of the problem is to simulate an old airport terminal display: your program must display a line of text in ASCII art.”

And as you can imagine, I gave this a shot, and to be honest. It was quite fun. I finished it, passed the tests and the hidden tests, and then the most exciting thing happened, I got access to other people’s solutions, ordered by votes (gamification, yey!). Of course, as you would imagine, I clicked directly on the top one, and oh boy, I got floored. It was at that very moment that something clicked. I found out why this approach, although fun for leisure and practice, this practice is so bad for evaluating someone, especially in time-constrained, high pressure, and high stakes scenarios. But, we are getting ahead of ourselves, back to the story.

If you took the time to check the challenge, awesome. If not, this is the gist of it.

You get an ASCII art font like this :

   __ ___ ___ ____ ____ __ ____ ____ 

  /__\ / __) / __)(_ _)(_ _) /__\ ( _ \(_ _)

 /(__)\ \__ \( (__ _)(_ _)(_ /(__)\ ) / )(  

(__)(__)(___/ \___)(____)(____) (__)(__)(_)\_) (__) 

You also get the width and length of a char of that font, and you need to write strings in ASCII. Quite straightforward, since this is not about solving the challenge itself, we will not spend too much time on the specifics.

The way I solved this was this: 

class Solution
{
    static void Main(string[] args)
    {
        int L = int.Parse(Console.ReadLine());
        int H = int.Parse(Console.ReadLine());
        
        var writter = new Writer(H,L);
        
        string T = Console.ReadLine();
        for (int i = 0; i < H; i++)
        {
            writter.PopulateLetters(Console.ReadLine());
        }
        writter.ToAsciiString(T, true);
        
    }
}
class Letter
{
        public int height { get; private set; }
        public int width { get; private set; }
        public int startPoint { get; private set; }
        public List<string> AsciiMatrix;
        private Letter() { }
        public Letter(int h, int w, int s)
        {
            AsciiMatrix = new List<string>();
            height = h;
            width = w;
            startPoint = s;
        }
        public void AddRow(string row)
        {
            AsciiMatrix.Add(row.Substring(this.startPoint, width));
        }
    }
class Writer
{
        public Dictionary<char, Letter> dict = new Dictionary<char, Letter>();
        private string charList = "ABCDEFGHIJKLMNOPQRSTUVWXYZ?";
        private int height;
        public Writer(int h, int w)
        {
            charList
                .ToCharArray()
                .ToList()
                .ForEach(c => dict.Add(c, new Letter(h, w, charList.IndexOf(c) * w )));
            height = h;
        }
        public void PopulateLetters(string row)
        {
            foreach (KeyValuePair<char, Letter> entry in dict)
            {
                entry.Value.AddRow(row);
            }
        }
        public List<string> ToAsciiString(string s, bool print)
        {
            var searchString = string.Join("" , s.ToUpper().ToCharArray().ToList().Select(x =>
            {
                return charList.Contains(x) ? x : '?';
            }).ToList());
            
            List<string> buffer = new List<string>();
            for (int i = 0; i < height; i++)
            {
                List<string> lineBuffer = new List<string>();
                searchString.ToCharArray().ToList().ForEach(e =>
                {
                    lineBuffer.Add(dict[e].AsciiMatrix[i]);
                });
                
                buffer.Add(string.Join("", lineBuffer));
            }
            foreach(string row in buffer){
                Console.WriteLine($"{row}");
            }
            return buffer;
        }
    }

Keep in mind that this, in my opinion, is straight of the top of my head, throw-away code, nothing fancy, nothing revolutionary.

Now, back to the story, after submitting your solution, you have the chance to see how other people solved it and vote, and naturally, as I said, I was curious how other people solved it and picking the most voted solution I saw this:

class Solution
{
    static void Main()
    {
        int L = int.Parse(Console.ReadLine());
        int H = int.Parse(Console.ReadLine());
        string Sentence = Console.ReadLine().ToUpper();
       
        for (int i = 0; i < H; i++) {
            string AsciiRow = Console.ReadLine();
            foreach (char letter in Sentence)
            {
                int index = char.IsLetter(letter) ? letter - 'A' : 26;
                Console.Write(AsciiRow.Substring(index*L,L));
            }
            Console.WriteLine();
        }
    }
}

Boom! Wait, what? I thought this is interesting. Let’s see how other people solved it… and amazingly, most of the solutions were along the same lines, people solving it in a few lines of code, some more elegant than others. But the theme was short and sweet.

At that moment, I started thinking, what is wrong with me? Since most of the solutions were in this different style, why did that not occur to me? 

The Epiphany

I have to admit that this got stuck in my head for a while. I was jealous. I wanted to do it also like the cool kids, and as you can imagine, I started doing a lot more challenges on multiple platforms. And yes, I was living the dream, was writing one-liners like a boss. And then something strange happened, while working on real projects, I caught myself doing this, and then I started to understand what was going on.

You see, all these platforms are designed to measure specific implementations for specific problems (based maybe efficiency/speed). In theory, there is nothing wrong with that, if we look at it from a purely technical perspective, strictly from a coding standpoint. With experience, you start to realize that some other “non-functionals” are quite significant, sometimes even more important than speed, whit, and technical prowess. Usually, the software is built by teams, and if team members have varying approaches to the same problems, you might not find the success you are hoping for.

We need more chefs and fewer recipe book users.

Dave Snowden – DDD Conf 2018

Let’s unpack this. Looking at the two code snippets above that practically do the same thing, what difference do you see? 

I have to admit that it is a weird question, so let me rephrase that:

When landing on a new project, say you need to update the rendering direction from left to right to top-down per column.

Which code would you like to find staring back at you?

So now, maybe you think that I am mean because this is just a challenge, throw-away code, and no one does this on real systems, right? 

Well, as I already mentioned, I tended to do this. And and probably more people do it; it’s mostly how our brain works regarding problem-solving and patterns of thinking.

Or you could say that according to TDD, the second approach is the right one, and the first is premature optimization, and you might be right. Still, we set the context at the beginning, businessy software, so in my mind, software should also encapsulate some business knowledge.

The problem 

Doing code challenges might not be a big problem by itself, but we can see the lurking danger if we start looking at it holistically. The reason behind this thought is, I think, an optimization problem. If we begin measuring these, people will start optimizing these particular skills to the detriment of others. Although knowledge of algorithms is essential, it is not as critical to spawning a quite lucrative sub-industry of people giving training and mentorship for passing these tests. In the end, we might end up with people excellent a solving fizz buzz questions but lack the experience and knowledge of actually building software.

To put it bluntly, when there is a system, people will game the system.

Also, I saw people argue that these tests show how candidates think. Still, for an optimization problem you see for the first time, with 30 minutes to solve, it only shows you have solved something similar in the past. Most of these tests have a specific implementation for which the tests were written anyway. You either get it or not, and you might write off someone with high potential due to the fact that they did not encounter that situation before or, for some reason, couldn’t fully concentrate in that roughly short time window. 

Another argument is that this is “best practice”. Well, what exactly does best practice mean ? The way I see, some thing to be considered best practice, is something that most people do, like a common agreed standard. But on the hand if everybody does something, does it means is good for you ?

Discovering what is important

I think this is one of the biggest conundrums that we have in the industry right now. What is important in software development? To only right/correct answer would be: 

It depends…

Consultant

I can’t tell you what might be important to you, but I can tell what I consider important when looking for new colleagues. 

When building teams I look for the following things:

  • a well rounded team with people that complement each other, let’s say for a team of 4 – 6 developers, is 3 are super technically oriented, I would try to find at least 2 whole are more process oriented, this way we avoid building “echo chambers”.
  • usually I look for team players rather than “rock stars / lone wolfs”, people that usually respond to question with “we” instead of “I”
  • people who have an openness to learn and adapt
  • people with the right know how

Now that we have this out of the way, let’s focus a bit on this “it depends”. 

It is all about what scenario you are in and what exactly you are looking for. 

There are different needs, and in some cases, it makes sense to have this as part of your process. Say like having to staff 40 developers to transform specs into code, factory style. On the other hand, if you are looking for experienced people who also need to do software design, coach people, negotiate technical solutions with other teams or requirements with stakeholders, this approach might not be the most lucrative.

As a takeaway, I think you should be very careful with global, one size fits all processes and try to discover your actual needs and create custom processes for specific roles. 

Processing…
Success! You're on the list.