Sometimes, a quick and easy programming language like Ruby might not be so quick and easy. Sometimes, C may be easier. Sometimes, you might complete a task faster with C than with your favorite scripting language.
I’ve long been a proponent of scripting languages. In particular, I’ve enjoyed learning and using Ruby. So when I was inspired to program a boggle solver as a code kata, I naturally reached for this nice shining tool in my toolchest. Solving the problem was fairly easy. It took me almost 3 hours to get the code working correctly and reading cleanly. I was fairly happy with the experience, but I felt it had gone slower than expected. The solution was also quite slow. To find all the words made out of non-repeating paths on a 4×4 grid of letters, the script takes about 10 seconds.
Then, about two weeks later, I went to our second code dojo event at Oslo XP meetup. Inspired by the programming there, I decided I wanted to implement boggle in C to see how fast I could get it to run. C would also force me to implement the data structure for the dictionary more directly, instead of using the Ruby built in classes.
Since I had just been practicing test-driven development, I decided to program the solution test-first, which is a bit tricky with an algorithm like this. I expected this to take a little longer, but I thought it would be a fun challenge.
So, what happened? First, the solution took me 1.5 hours to implement (half the time!). Of course, being C, it ran in about 0.5 seconds instead of Ruby’s ten seconds.
The experience has left me puzzled: Why was it so much easier for me to implement the C solution? Some possible explainations:
- Having thought about the problem before, maybe it was quicker to solve it the second time around? Actually, I had thought about the problem a bit before. I solved it first in C# about four years ago, and I already had a working algorithm that I basically wrote down when I started.
- Having a more powerful language, I became more ambitious? This is a very likely component. The Ruby solution is able to read a list of files describing the board as command line arguments or by reading from standard input. Not wanting to do anything that wasn’t needed, the C program is much less fancy. It just reads a file with a hardcoded name from the current working directory.
- Having a more powerful language, I spent more time reading the documentation. This was certainly true. Most high level languages have a lot of useful standard library classes. Sticking to plain old C made me able to focus on the problem instead of the tools I could use to solve it. As it turns out, a struct isn’t that much harder of a dictionary representation than a struct-implemented tree.
- Programming test-first, I kept my focus on the task at hand. I wrote a small, but critical set of unit tests for C, which in Ruby, I just played around it until it worked. The test-driven approach is much more effective (for me, anyway)!
The next day, I wrote a Ruby script that reorganized 25 Java modules implemented in Maven and updated all the configuration. This was actually much less painful than I expected. It just goes to show that there is such a thing as the right tool for the job.
My conclusion from this is that there’s much more to effective coding than choosing an effective language. Staying focused on the task at hand is the single most effective productivity enhancement technique I know. Stay away from extra functionality (“gold plating”) and fancy tools, and write your acceptance criteria as tests before you start with a task.