Wednesday, March 4, 2015

Kata: Mars Rover in Clojure using multimethods

Yesterday we had a coding dojo in Clojure Developers Barcelona meetup.

We practiced together doing the Mars Rover kata.

I had already done this kata in Java and C++ before (several times) using the state pattern to eliminate all the conditionals on the rover direction and the command pattern to decouple the translation from the messages sent to the rover into commands acting on it.

As usual I used a mix of TDD and work on the REPL to code this Clojure version.

To document the process I committed the code after every passing test and every refactoring and also committed the REPL history. You can find the commits step by step here.

After making the rover rotations work I had a huge cond on the rover direction with an if branching on the command value inside each case.

It was time to refactor.

The suggestion in the kata was to try to eliminate conditionals using maps, multimethods and/or protocols.

First, I used multimethods, dispatching on the rover direction and the message it was receiving just to see how multimethods work.

It took me a while to make it work because I had a error in the arity of a defmethod and the stack trace was difficult for me to understand.

Then I realized that it was much better to separate the translation of messages into commands from the commands themselves. To do it I used a map that associate each message to the command multimethod:

Here you can see one of the multimethods:

From here on, coding the remaining commands using TDD was very easy. I just had to write a failing test and then make it pass by implementing its corresponding defmethod.

Once all the possible commands were working, I started with the functionality of wrapping the rover in a world.

If you check the commits, you'll see that I tried several approaches here because I wasn't sure how to model the world.

In the end, I decided to model the world as a map with a :wrap-fn key associated to the wrap function for a given kind of world. I passed the world map as a keyword parameter to the receive function which had a default value equal to infinite-world whose :wrap-fn was the identity function. That way all my previous tests continue to work without having to change them.

Then I started doing TDD to code the wrap function for a kind of world called squared-world which was created by a factory function by the same name.

Finally, I started with the obstacles which were modeled as a list of positions (which were represented by maps like {:x 1 :y 2}) associated to the :obstacles key in the world map.

To code the hit-obstacle? function I used the REPL for the first time (you can check all my tests on the REPL history which I also committed) to try to make it work using the some function.

After that I just added a validation to check if the initial position of the rover was on an obstacle.

These are the resulting tests using Midje:

and this is the resulting code:

I'm not sure if this is a good factorization for this problem in Clojure, (I feel that what I did for having different implementations of the wrap function is still a bit OO-ish), but it was a good exercise to practice with multimethods and start exploring their possibilities.

You can find the code in this GitHub repository.

Next time I'll try doing the same exercise using protocols instead.

I enjoyed a lot this coding dojo.

Thanks everyone for coming and Akamon for letting us use its facilities.

Saturday, February 28, 2015

Scala Developers Barcelona TDD introduction session

Two weeks ago I facilitated an introduction to TDD in a Scala Developers Barcelona event.

First, I gave a very short introductory talk about TDD, (these are the slides).

After the talk, I coded a simple exercise to help the attendants get a feeling of the TDD flow.
I tried to stress the importance of creating a list of examples first and choosing the next test so that the code could grow in small steps. I also talked about wishful programming, going from red to green quickly and the importance of refactoring to sustainable TDD.

I used Clojure to code the exercise.

I feel that, somehow, using Clojure got in the way of the message I wanted to transmit. Next time I'll use a language which is more familiar to all the attendants.

This is my solution to the exercise in Clojure where you'll find commits after each passing test and each refactoring, so you can follow the process.

Finally, we started doing TDD with a simple kata.

Ignasi, Jordi and I were all the time visiting the different pairs, helping with doubts about TDD or Scala and commenting with them how their solutions were growing test after test.

I think that during this time I had the chance to clarify some things that hadn't come across before because of the lack of familiarity with Clojure.

At the end, we had a short debate about TDD.

I'd like to thank the Scala Developers Barcelona organizers for inviting me to facilitate this dojo. I had a great time and I hope that, the attendants could get something useful from it in spite of my using Clojure for the first example.

I'd like to also thank all the attendants for coming and Álvaro for telling the Scala Developers Barcelona organizers about me.

Monday, February 16, 2015

Clojure Developers Barcelona: Introductory talk about Clojure functions

Last week I gave a talk about Clojure functions for some of the Clojure Developers Barcelona study group members.

This is the the code I showed on Lightable to explain a bit about Clojure functions:

I had a great time and learned a lot preparing this talk.

During the talk I mentioned some destructuring techniques I had explained more deeply in a previous talk.

This time there were many more attendants than in previous events of the group which is really great.

Thanks all for coming!

I hope we'll go on learning together in next events.