At work the other day, conversation on a mailing list fell to the fact that most programmers can’t write FizzBuzz. For those of you who haven’t heard this discussed before, the point is that you set the most trivial possible programming task for interview candidates: Write an algorithm that prints numbers from 1 to 100, except that it should print “fizz” instead of multiples of 3, “buzz” instead of multiples of 5, and “fizzbuzz” for numbers that are both. A full implementation in the most straightforward way involves just two control structures: A
for loop wrapping round an
Naturally, since we are all programmers and somewhat competitive, we had a go at solving the problem ourselves in the most “creative” way possible. I had a number theoretic solution (repeatedly sum the digits of the number until you have a single-digit number, then compare against 3, 6 and 9 to determine whether it is a multiple of 3) and a slightly more elegant solution involving
itertools in Python: one iterator produced the “fizz”s, another iterator the “buzz”s, and an
imap knitted them together into a single sequence.
My second solution was controversial: some thought it was elegant and idiomatic Python. Some thought that it was pretentious obfuscation. I’m going to argue that it’s impossible to tell which of these is true.
Good code is about the relationship between the problem domain and the representation in code. The problem domain is comprised of the stuff that is known by the person with a problem to solve. We can assume they’re intelligent, but they don’t (and shouldn’t need to) know anything about how the program is implemented. The best code preserves and makes accessible the relevant aspects of the problem domain, and minimises the interference of “accidental” details of programming that have no representation in the problem domain.
I maintain that the FizzBuzz problem domain is so badly under-specified that it’s impossible to know how a really good solution would look. There are lots of problems that are isomorphic to FizzBuzz but have different characteristics, that would (if the problem were not so trivial) ideally be approached in different ways. Perhaps “fizz” and “buzz” are two entirely different concepts that different parts of the business want to talk about, in which case my dual-iterator solution might help to make this plain. Or perhaps it’s going to be extended into some kind of number theoretic analysis, in which case we should write our code so that the mathematical properties are foremost (perhaps we introduce a prime factorisation concept from the start). Or maybe we’re writing single-use code for the accounting department to produce a report during the merger of two companies.
I hope it goes without saying that simplicity is also an important feature, and that in the case of something as trivial as FizzBuzz simplicity ought always to win out over other concerns. But sometimes when programmers talk across boundaries of industry and experience it’s necessary to treat toy problems as if they were a bit more than that, and I felt like there was some mileage in that this time.