Tuesday, November 5, 2013

Interview questions and real software engineering

Note: This post started as an exploration of interview questions; however, the problem space is much bigger than that. I'm trying to really understand what software engineering  is and why some people are much better at it than others.

As far as my experience goes, there seem to be four kinds of hiring strategies employed by various companies. They often come in combinations, with different values attached to different parts.

  • First comes the classic HR questionnaire that you have to fill out and/or answer in person. It's about personal values, why you want to work for a company (hint: "because I have no money" is not the right answer), etc.. This can essentially be replaced by a single question: "are you happy being a replaceable gear?". Tends to be mostly absent these days in pure-tech companies, but is still employed by large corps with IT departments, e.g. banks or defence contractors.
  • Second comes the "I know you already" kind. Very popular among startups and companies entrenched in Open Source - they essentially view your work on GitHub and/or know you already from conferences and it all boils down to an informal chat to establish whether you are the right match. If there is a technical interview, it's very informal and mostly revolves around technology choices and the rationale behind them. These companies also tend to have a decent way of exploring the common ground in the first month or week, so the decision to hire is not permanent.
  • Third is the classic knowledge-based questionnaire. They'll ask you unusual tips & tricks in the technology that you know (or you don't), like handling of **args in Python or whether can you do some magic JOIN in SQL. Usually these answers can easily be googled, and while the rationale is "if you know all these quirks you have spent a lot of time on this platform", it heavily favours people like me with a photographic memory for obscure details. This photographic memory usually brings no value whatsoever - I know a lot of crazy details about all kinds of platforms that are completely useless. If you want to impress the potential interviewer, put the BUGS section from a random manual into your fortune cookie each time you start a terminal.
  • Last, but not least, is the classic "Google-style" interview. It involves asking you questions like this one. You have a well-defined problem and you have to find the right solution. There are a few good solutions, but only one that's really correct. The problem space is very finite. Repeat for the whole day in stressful conditions, until you're tired (and way after that).

So once we have categorized these groups, let's have some opinions. First I would like to dismiss the classic HR one as not applicable to the software development I know. I can't imagine a good project where people are treated as replaceable gears. The third kind, and to some extent the fourth kind have some sort of correlation to real knowledge, but there is definitely no causation -- the only thing you can say is that a person who does not know a platform at all will not be able to answer questions about its quirks. We have something to work with, but the problem with it is that your company does not exist in a perfectly uniform vacuum. If everyone does these kinds of interviews, the candidates who know these quirks will have a lot more job offers than those who don't. At the end of the day, if you're the only company who does not do that, you can hire all the good people who don't have photographic memory and you win.

Now, let's sidestep a bit and talk about how software development really works in my opinion. The sequence looks vaguely like this:

  • step 0 - customer problem "I want to send messages to my peers"
  • step 1 - technical problem "we need to send messages between computers with browsers"
  • step 2 - technology and architecture choice "AJAX program, JS logic, Python in the backend, HTTP"
  • step 3 - implementation overview "this is the backend API, JS has to respond to this..."
  • step 4 - actual implementation (bunch of code, usually a lot)

Where each step corresponds to moving from the previous state to the next. Eg. step 1 means "understand what customer wants and explain it in technical terms".

Now, as a person working for a company as a software engineer, especially a large company you might not participate in steps 1 or 2. Working for a startup or a small company will require you to deal with it much more, so the interview style where you just chat makes a lot of sense. After all, this will be your primary skill.

The problem with the rest is that step 3 is the hard step these days, since we don't code on punch cards in assembler. However, most interviews will focus on step 4 -- which is not quite, but almost, purely mechanical. In my opinion, the difference is as follows:

  • step 4 covers a problem space within constraints that make it finite and explorable. An interview concentrating on this will cover how quickly you can navigate a finite space. I believe this step can be solved completely by better programming languages.
  • step 3 covers a space which can be considered infinite - the number of possible combinations is just too large. Most of actual software engineering revolves around "I need to find a simple solution for this formal, but vague problem. How do I constraint my infinite space so that it's possible?".

Note that even in a completely formal environment -- like implementing PyPy, which is a Python interpreter -- step 3 is far more important than step 4. You're presented with a piece of code to be optimized. You need to find an optimizer model that's simple enough and correct to optimize this piece of code. While the problem is formal, the potential space is infinite, so you need to constrain it in various ways first, before making any real progress. Once you have done that, the actual task of e.g. writing a tree-walking algorithm correctly is trivial.

Now, to summarize, I don't really know how to conduct technical interviews that cover the most important parts of software engineering. I think a lot of interviews focus on the wrong things and only vaguely resemble what is actually happening. That's why we generally go with "let's have a chat and we'll see as we go along", but maybe there are better ways. I don't think enough research has been done on the human ability to explore complex systems, but on the other hand I might just be highly ignorant of that topic. Please mail me interesting papers if you know some.

On a sidenote - we're hiring. If you want to work with smart people on challenging problems, get in touch. Contact info findable courtesy of google ;-)

Maciej Fijalkowski