Writing Code On Whiteboards Is Hard

Writing Code On Whiteboards Is Hard

  • Comments 87

Work has been crazy lately and I haven't had much time to work on SimpleScript.  It's a lot of work starting from scratch! Right now I'm writing a templatized hash table for the binders and other lookup tables.  I haven't written templatized C++ for a loooong time and its slow going.  I hope to have the named item logic done over the weekend, so that I can explain how the module system works next week.

Until then, here's an article I wrote a while back on interviewing that I never got around to putting up on the blog before now.

Writing Code On Whiteboards Is Hard

As I've mentioned before,  I occasionally interview candidates for development positions on my team and occasionally other Visual Studio teams.  Plenty of people have written plenty of web pages on interviewing at Microsoft, so I won't rehash the whole story here.  What I wanted to mention today was some words of advice for candidates for development positions. This is by no means complete -- I want to concentrate on one important aspect of the interview.

Dev candidates: if you've done any reading at all, you know that most of your interviews will involve writing some code on a whiteboard.  A word of advice: writing code on whiteboards is HARD.  Practice!

It's hard in part because you don't have intellisense or syntax colouring or any of the other tools at your disposal that you normally do when writing code.  I know that, and I'll take that into account.  I don't care if you write memset(&b, cb, 0x00) when you mean memset(&b, 0x00, cb) -- I don't remember that stuff either.  I don't care if you forget semis or make other syntactical gaffes.  I'm not looking for people who can spit out syntactically perfect code at the drop of a hat; that's not the point of the coding exercise at all.   I'm trying to find out how you solve problems.  Do you:

  • rush right in and start coding without thinking the problem through first? 
  • find areas where the problem is ambiguous and clarify them, or do you make a bunch of assumptions?
  • break the problem down into pieces?
  • do the easy pieces, paint yourself into a corner, and attempt to handwave your way out of the situation, or work on the hard stuff first?
  • have any confidence that your solution is correct?
  • do anything to prove to yourself and me that it is correct?

It would be wise to make it easy for me to see that you're a well-organized person with good problem solving skills.  Leave lots of space -- you might need to stick in some extra lines.  Write slowly and clearly.  Explain what you're doing as you do it.  If the code is clear, well-organized, legible, and at least vaguely syntactically correct, it will be a lot easier on both of us to tell whether the code is well designed and bug free.  Walk through some simple test cases -- don't just dash down some code and say “yep, that's correct!“

The vast majority of the coding problems people pose do not require any "aha!" insights or rocket-science algorithms.  No one is going to ask you to implement a 4-5 Runge-Kutta differential equation solver.  We're going to ask you to implement a hash table or replace every instance of "foo" in a string with "bar". Eric Carter has a copy of Schaum's Programming With C++ in his office because that thing is a gold mine for interview questions.  Got a technical interview coming up?  Pick up a copy of any introductory programming text, pick a few problems at random, and solve them on a whiteboard.  Heck, I'll flip through it at random right now.  Here are some sample problems taken from various places in the book:

  • implement a method which determines how many characters the string pointer must be incremented to point to the trailing null.
  • implement the less-than operator for a class representing rational numbers as (numerator / denominator) pairs of integers
  • implement function that takes an array of integers and returns the maximum, minimum and average.
  • implement a template for generating stack classes
  • implement a program that shuffles an array into a random order

Any of those would be a highly typical coding question.   And before you say "that's easy!" about any of them, think about what's missing from those problem statements before you write the code.

That string pointer: What encoding is it pointing to? 7-bit ASCII chars, UTF-8, UTF-16, some ANSI encoding?  Are you going to ask the interviewer, or are you going to assume that you're writing C code for some operating system that existed in the Before Time when there were no strings that contained Chinese characters?  Hint:  Microsoft writes very little C code targetting PDP-11 machines.  Ditto for programs that never have to deal with non-Roman character sets.

That less-than operator: Do you have to handle nonreduced fractions like 2/4 ?  Illegal fractions like 2/0?  Can you assume anything about the size of the integers?

That array you're shuffling: do we care if a hacker can predict the sequence? Do we need crypto-strength randomness, or reproducible pseudo-randomness?  Is this for an online poker game for real money or a test case for a sort algorithm?

And so on.  None of these problems is well-defined enough that I'd feel comfortable writing production quality code without at least some clarification.

Candidates often make the mistake of concentrating on the code, like the code exists in a vacuum for its own sake.  That's a very unrealistic assumption!  Code not only has to be well engineered and correct, it has to be maintainable, testable, and solve a real customer problem.  In your interview, when you're done writing the code, think about:

  • how would a tester attack it?  Is the design even testable?
  • does it handle stuff that hostile/buggy callers are going to throw at it?  null pointers, large denominators, huge arrays? 
  • does it work well with other technologies?  that is, does it use the conventions of COM or ATL, or does it work against them?
  • is it correct, robust, maintainable, debuggable, portable, extensible? 
  • how would you know whether this was the code the customer wanted or not?

Now, this is not to say that someone who automatically thinks char * when they hear “string“ is an automatic no-hire.  But I am a lot more inclined to believe that “experienced in COM programming“ on your resume if you acknowledge the existence of BSTRs!  Also, I recognize that fresh-out-of-school candidates often have very little experience with these sorts of “real world“ considerations; I cut them some slack in those areas and concentrate on their raw intellectual horsepower, coding talent and long-term potential.

Finally, let me reiterate that technical interviews are hard, and even bright people screw up on them sometimes.  Two teams no-hired me when I interviewed for full-time positions here!  But that's another story.

  • > not to knock STL here, but there's engine code that gets called millions of times per second and it's important to understand what the compiler is spitting out. I get tired head staring at a pile of maps and iters and templates and trying to figure out if it's going to spill my registers.

    Way back in 95 I worked as a developer at a small company doing multi-user games. For a Doom-like shooter I developed the 3D rendering engine (over DirectX 1.0). I coded in C, then I had the compiler spit out the assembly code for the internal rendering loop, then I hand-optimized it. The result was a significant performance improvement. Fortunately, thanks to Intel, those days are gone.

    The operation of modern CPUs is so complex that it's practically impossible to hand-craft optimal assembly code. Instead we must learn to trust our compilers' optimizers. Assuming you are using a good compiler, such as VC7, the C++/STL combo becomes a very good choice.

    When Stepanov developed STL he realized that C++ programmers would only use it if the code generated was as efficient as the code they would write themselves. In fact, in most cases it's more efficient and more correct as STL developers are usually very smart people. Using techniques such as template specialization and massive inlining allows the compiler to optimize the code significantly for the particular task at hand.

    For example, STL makes it straightforward to utilize custom memory allocators. Will Eric take the time to add this capability to his templatized hash table?

    All this is not to say that STL is not without it's limitations:
    1. You must gork the STL way in order to make good use of it.
    2. Since STL make extensive utilization of templates, you need a modern C++ compiler to take full use of it. The STL implementation that came with VC6 for example was limited because of this.
    3. Compiler errors in code that uses STL can be difficult to track down. But this is true for all templatized code.
    4. Debuggers are still mostly ignorant of STL containers, which means that viewing their content can be a pain.

    In addition, you must enable optimizations to get high performance from STL. The ini parsing code I mentioned above that ran in 1.2 seconds, took 2-3 minutes when compiled for debugging.
  • Well, there's two ways to solve a particular problem -- you can solve the particular problem, or you can solve the general problem and then apply that solution to the particular problem.

    As for custom memory allocators -- if I roll my own, I'm going to solve my particular problem, not the general problem! I'll add custom allocators if I need to, but I don't think I will.
  • > Well, there's two ways to solve a particular problem -- you can solve the particular problem, or you can solve the general problem and then apply that solution to the particular problem.

    STL, now a part of the C++ standard, is obviously a general purpose tool. The beauty of it is that, thanks to generics and specialization, it's often as efficient as custom code created for a particular purpose.

    For more information on the techniques that make this possible in C++, I highly recommend reading Modern C++ Design by Anderi Alexandrescu.
  • Wonderful insight. I too have gone the 2 team no-hire route so hopefully the 3rd time is the charm. Do you think you did anything different the 3rd time that you think may have gotten you hired? The 2nd time I interviewed, the recruiter said everyone was impressed but she doesn't know why they said "no" (it was for Windows core team or whatever you call it). I'll definately put into practice the things you mention here. Thanks.
    P.S. Want my resume? :-)
  • > Do you think you did anything different the 3rd time that you think may have gotten you hired?

    There was no third time. I was extended an offer on the VBA team on the strength of twelve months of internships. Former interns are encouraged to look around, so I interviewed with the Blackbird team (bonus points to anyone who remembers that thing!) and the SQL Server team; both no-hired me.

    > Want my resume? :-)

    All I'd do with it is send it to the recruiting department, so you'd be better off just doing that yourself.
  • > everyone was impressed but she doesn't know why they said "no"

    Sometimes people are good candidates overall but bad fits for a specific team.
  • When Microsoft flew me out there for an interview I was all prepared to write code on the white board. But when I was asked to write the QuickSort algorithm, that kill all my chances of getting the position. :-/ Not bitter about that, I swear.
  • Why do you think that killed your chances?
  • Take Outs for 15/16 April 2004
  • Have you ever considered using a computer for technical interview coding questions? If you expect the candidate to write c# code, for instance, you could have a machine with VS (and NUnit?) up and running with and a projector. Why not use the tools that are good for coding to test coding ability? I think the way a developer interacts with the dev environment can tell you a lot about how he or she works. Is this person able to use the tools available to solve problems?

    Maybe offer both the white board AND the computer to solve the problem. Now you get to see where the person starts, at what point he or she moves to code or to the board, how and when intellisense and help are used, what questions are best answered on the board or in code, etc.
  • I am a recent grad and in school we could ONLY use the paper approach! During tests and such we had to have 100% syntax perfect, 100% correct solution.

    I remember one of my MFC exams; we were forced to write a 100% serializable class and GUI system. (The rest of the test was Linux GUI coding).

    Doing this on the white board for new grads will most likely be easier than for long time coders (Just an assumption). Although it is true, a lot of the real world problems are not tackled in school.

    My only downfall is... I live very far away from Microsoft’s HQ. I live in Toronto, most of the Microsoft recruiters probably do not even look at my resume =(
  • Dude, first of all, I grew up in Waterloo, just down highway 401 from you. Second, I have coworkers from Jordan, Bulgaria, France, Italy, South Africa, Russia, Malaysia, China, Japan... and that just one hallway. All of them came from considerably farther away from Seattle than Toronto.

    I assure you that recruiters get and read thousands of resumes A DAY from places farther away than Toronto!
  • Thanks for the info Eric and by the way Waterloo is a nice place. Of course they read thousands of resumes a day, but the problem with that is they look at experience... look at location... create a *uhh* sound... move on. I know alot of recruiters (not MS) who sometimes skip the skill set information on the resume.

    Microsoft is a great company and I continue to defend it (even during all those Linux open source conferences ;) ) but some times new grads get better *luck* at smaller companies.

    But I will continue applying for jobs at MS and see what happends!

    Any more insight Eric is much appreciated from us all ;)
  • And people from from Down Under!!
Page 2 of 6 (87 items) 12345»