Last Saturday, I attended the Global Day of Code Retreat. I found
out about the event in my Twitter stream, and when I signed up for
the event, I did not have much of an idea of what it would be about,
except code. With some research, I found that it would be a day of
using Test Driven Development practices to improve on coding style
and quality. Fair enough I thought, got myself a book on TDD (which
I have always wanted to do more) and reserved my seat, which was
free.
The event was hosted by immobilienscout24 and
sponsored by Nokia. Sponsoring
included catering, and as the day started at 8:00am, the
availability of a breakfast was very welcome. The crowd consisted
of some 30 hackers. An informal poll showed that most of them
were either using Java or Ruby as their first language, a few were
into JavaScript. One guy said that C++ was his primary language,
and I was the only Common Lisp hacker.
The format of the all-day event consisted of six sessions of 45
minutes. In every session, people would form new pairs and
implement parts of Conway's
Game of Life using TDD practices. For each session, the pair
chooses a specific challenge or goal to solve. At the end of the
session, every pair deletes their code, discusses what they
learned and then joins the group to share their thoughts.
The focus of the goals and challenges was on TDD practices. For
about a half of the participants, TDD was already part of their
daily work routine. The other half had heard of TDD, like myself,
and joined to learn about it in the event. For me, this was one
of the bigger takeways. I found it very helpful to pair with
people that practice TDD in order to learn how they'd go about to
write a test before they'd write an implementation. It seems that
the TDD school favors a very small test granularity. As was
explained by the organizer of the meeting, one would write very
small tests that exercise very small aspects of the production
code initially, and then build up on that.
In the six sessions, I used Java, JavaScript and Common Lisp. For
Java, the organizers had come up with a skeleton project that
included a unit testing environment (jUnit?). For JavaScript, I
had prepared a simple browser based environment with QUnit, for
Common Lisp I used Clozure CL and the simple unit-test
library that I have used in the past.
Here are some observations:
The Java dudes travel with heavy baggage
IntelliJ was the most
popular IDE among the Java folks that I've talked to. I am split
between admiration and disgust when it comes to what seems common
practice in the Java world. I'm used to write code by thinking
about what I want to write, then typing the stuff that I've
thought about. With Java and IntelliJ, the process is more
interactive with the IDE, i.e. the programmer types a few
characters, the IDE displays some menu to choose from or
automatically adds code and so on. This is nice when the IDE
automatically recognizes, say, that you are using a name of a
class that has not yet been defined or imported and then offers
you to either import a package that defines a class of the name
that you've typed, or to create a class skeleton (including all
the boilerplate and ceremony that Java wants) for you.
While this appears to be convenient, it also does not always work.
In both of my Java sessions, the IDE got confused in some way or
another, which was not fatal, but still annoyed me. Also, the
static nature of Java slowed us down. For one, even though Java
does have all the nice data structures (we wanted to use a set of
coordinates), we wasted a lot of the short session times
converting data types and supplying boilerplate that allowed us to
actually put coordinate objects into a set. Also, file based
compilation took time - Not minutes, but seconds. I was assured
that one would use libraries and code generators in production
code and that desktop machines were faster in compiling, but I
still can't really relate Java to Agile, in the sense of the word.
Also, the use of code generators in IntelliJ makes me wonder how
one maintains such code. How can one actually distinguish between
what was carefully crafted and what was pasted, from templates, by
the IDE? In my eyes, this is like copy and paste programming with
the copy step optimized into templates. I'm not the first to say
that and it does not come as a surprise either, but it was an
interesting experience for me nevertheless.
Pair programming is fun
Being a remote consultant, I rarely have the chance to interact
over code with other programmers. This was something I found
enjoyable to practice, even in languages and environments that I'm
not familiar with. It is amazing how vastly different the
approaches to implementing a relatively simple thing can be, and
compared to code reviews - in particular if they're done by email
- it is much easier to make suggestions in a constructive
way. In that respect, writing code that is supposed to be deleted
also helps concentrating on the essence as no sense of code
ownership is developed.
I found the pair programming experience significantly impacted by
the fact that programmers use different coding environments.
Working on an unfamiliar keyboard and with an unfamiliar IDE is a
real productivity killer. I'd hope that in a team that pairs
regularly, the work environments are more standardized than they
have been on this event. I was using Emacs for my Lisp and
JavaScript sessions, and my partners had a hard time getting
along. What I found rather interesting was that the guys who
wrote JavaScript in my Emacs always mimiced what their IDE would
do for them. Rather then writing "if (foo) { doSomething()",
they'd type "if (foo) {}", then navigate into the braces with the
cursor to code along. This is kind of curious because it seems
that the balancing of parentheses, brackets and braces is much
more of a chore in other languages, to the point where people slow
themselves down a lot if not aided by an IDE to the balancing for
them. We Lispers, with only the parentheses to keep track of,
have a much easier life, in particular with Emacs doing the
indentation for us.
Is TDD the kool aid?
In some sense, I am sceptical about TDD. Testing is a great idea,
and doing it in a disciplined fashion certainly helps writing
better quality software. Also, automated tests are really the
best way to prepare software for change. But, and this is where
this Saturday could not convince me, I don't believe that spending
time on writing very fine grained unit tests for every aspect of
of a program helps preparing it better for refactoring
and change. I think that testing against external requirements is
the real key to writing programs that can be changed facing
changing requirements, and that it should be possible to relate
every test to some requirement. I must admit that one
Saturday of TDD does not give me sufficient experience to judge, though.
Common Lisp and TDD
Some of the TDD discipline probably owes to development cycle in
statically compiled languages. Where we Common Lispers have a
rather incremental style and do our testing interactively in the
repl, developers in languages like Java or C++ write larger chunks
of code before they plug it together to do something meaningful.
Such environments give the developer less insight into the
run-time behavior of a running system, and tests are a way to make
sure that more of the interactions of the system components are
actually exercised.
I am not claiming that an interactive development environment
makes testing less useful. In such an environment, though, it is
common to write and test a function in small, iterative cycles.
Furthermore, through the use of a tracing facility, the dynamic
bahavior of a system can be observed at any time, without the need
to touch or recompile the code.
In any case, this was a very nice experience and I'll go to a Code
Retreat again, if I can. For that, I'll probably prepare myself
for Java tools better in order to get more out of pair programming.