Monday, June 13, 2011

Programming with the Stars at GOTO Copenhagen 2011

At GOTO Copenhagen 2011, we had a track called Programming with the Stars. It gave me a unique chance watching five software professionals along with an audience member solve the same (simple) problem in different programming languages, using different programming paradigms. It would be a shame not to reflect a little on what I learned that day.

Overview
In every time slot, a speaker was asked to solve the Tennis Kata along with a volunteer from the audience. The big idea was to start discussions on how to write code, how to apply different programming paradigms, and to show off the different languages and techniques to the audience.

First, Ulf Wiger did the Erlang presentation. There was even media coverage on this presentation. Ulf was very relaxed and cool and showed a lot of nifty language features. Alongside his text editor, he had a console where he poked around in the running code, showing how it worked. The result can be seen here.

Then, Patrick Linskey did a solution in Java. The result can be seen here. Apart from doing a solution in Java, Patrick was keen to check code into Git along the way, and we had a unit test showing that the code worked. I ended up as his partner, since the Java audience was a bit shy. It was great fun.

Next up was Mark Seeman in C#. Mark is a hard-core TDD master, and his partner clearly had no TDD experience. This was an extremely entertaining learning experience to everybody, as Mark was struggling to keep his partner from writing code before test and keeping things simple. The result can be seen here.

Talking entertainment, Sam Aaron was up next for the Ruby session, and he brought with him a monome. He had programmed it so that when he ran the tests (or rather, RSpec specifications), it would flash the right colors and perform adequate sounds based on the test outcomes. The result can be seen here. Frank Vilhelmsen took some great pictures of the event.

Finishing off, Christophe Grand showed us how to do the solution in Clojure (with Sam Aaron as partner, in fact). Just as Ulf, Christophe tried out the solution in a console (the so-called REPL) while writing the code. The result can be seen here.

Programming styles
Of course it's unfair to use the results of the different time slots as representations of the programming styles used in the different programming camps, since the track was more about process and learning than the actual result. Unfair or not, though, let's dive in...

I've started to appreciate Erlang. I used to think that it could only be used for telecommunication hubs and other stuff that was irrelevant to me, but Ulf showed lots of nifty stuff. Pattern matching works well in Erlang, and record manipulation is concise. However, it still feels a bit old-fashioned to me, e.g. you cannot reference fields in records in other modules by name until you specifically load a record definition. Ulf explained that there was a reason for this (very loose coupling, so you can upgrade parts of your application).

The Java solution is different from all the other solutions in that it models players and a game, and we have a definition of a finished game, a winner and all. This is probably overkill for the simple Tennis Kata game, but is typical Java. Why do we Java programmers over-engineer like this? Java is very verbose, so we probably wouldn't have had the time to write all this code without a proper IDE.

The C# code ended up very simple, since Mark was struggling to get the process straight. He used AutoFixture as a testing tool, something I'd really like to try out soon. We didn't get to see much of it, but it seems like a nice testing productivity tool. My verbosity comments for Java mostly apply for C# as well.

Ruby... I love it. The code, the specs, it all looks and feels natural to me. Compared to the two functional language results, though, I do see that it's a little verbose. However, I think it's OK to be a little bit verbose, as long as the verbosity serves readability.

I have to admit that I still haven't learned to appreciate Clojure. The technology is really cool (memory transactions, persistent data structures, etc.), but the LISP style is a problem for me. The following Clojure code:

(defn result
  "Returns a string representation of the game."
  [[score-a score-b]]
  (cond 
    (= score-a score-b) (if (>= score-a 3) 
                          "Deuce"
                          (str (points score-a) " all"))
    (and (> score-a 3) (= score-a (inc score-b))) "Advantage A"
    (and (> score-b 3) (= score-b (inc score-a))) "Advantage B"
    (and (> score-a 3) (> score-a (inc score-b))) "Game A"
    (and (> score-b 3) (> score-b (inc score-a))) "Game B"
    :else (str (points score-a) " " (points score-b))))

can be written (almost) as concise in Java/C#/Ruby:

String result(int scoreA, int scoreB) {
  if (scoreA == scoreB) {
    return scoreA >= 3 ? "Deuce" : scoreA + " all";
  }
  if (scoreA > 3 && scoreA == scoreB + 1) return "Advantage A";
  if (scoreB > 3 && scoreB == scoreA + 1) return "Advantage B";
  if (scoreA > 3 && scoreA > scoreB + 1) return "Game A";
  if (scoreB > 3 && scoreB > scoreA + 1) return "Game B";
  return points(scoreA) + " " + points(scoreB);
}

I don't know... what you like the most probably depends on what you're used to.

To test or not to test?
Both the Java and C# examples were made strictly TDD, and I think it worked really well. Having the tests drive the design enables the audience to follow exactly what's going on. At the end of the session, everybody knew that the solution worked.

It seems like test-driven development is having a hard time in the functional language fragment. Just try looking up "testing" in Joe Armstrong's Erlang book, and you'll see what I mean. It's easy to start up a prompt and mess around with your code and obtain confidence that way, so perhaps that's all a functional programmer needs? I'm a bit curious about the effect this has on long-term projects with many team members, though.

The really interesting case was the Ruby session. Sam and his partner started poking around with no tests, just to get some basic design fleshed out. That worked well. However, they held back doing the tests for too long, mainly because Sam's partner and part of the audience didn't feel it was necessary to start testing. However, when finally they started doing RSpec tests (with the monome!), they went from having no clear idea about their state to knowing exactly what worked and what needed to be done next. An amazing transformation!

Different cultures
Whoever turns up for a specific session depends on lots of things on a conference, but it was interesting to reflect on the audience for the different sessions.

The C# audience seemed pretty young and enthusiastic. The Java audience was the biggest, but also the most shy: nobody volunteered as Patrick's partner, and there were very few comments from the audience during the session. The Clojure session was packed with other speakers from the conference.

In conclusion
Being part of the organization team, I was supposed to stay at the track the whole day, and that turned out to be very rewarding. Seeing people with experience in the 5 different languages and paradigms solve the same problem gave a much better feeling of the languages than reading 5 different introductory articles.