Home > English, Erlang > Improving your Erlang programming skills doing katas

Improving your Erlang programming skills doing katas


There is one sure thing about programming: you should try to improve your set of skills in a regular way. There are several different methods to achieve this kind of result: reading books and blogs, working on your own pet project and doing pair programming are all very good examples of this, but today I want to introduce you code kata. What is a kata? Well, since you ask, you won’t mind if I digress for a while first!

What is a kata?

In Japanese, the word kata is used to describe choreographed patterns of movements that are practised in solo or possibly with a partner. Kata are especially applied in martial arts because they do represent a way of  teaching and practicing in a systematic approach rather than as individuals in a clumsy manner. If the concept of kata is still not clear (shame on me!) you just need to watch again the movie Karate Kid. For the whole movie Mr. Miyagi San teaches Daniel LaRusso the importance of kata and we know that Miyagi San is always right!

The basic concept behind kata is fairly simple: if we keep on practicing in a repetitive manner we can acquire the ability to execute movements without  hesitation and to adapt them to a set of different situations without any fear. Pretty cool uh?

Coming back to the good old world of software developers (and especially Erlang ones) we may ask ourselves: “how can we apply the concept of kata to our daily routine?”. David Thomas (one of the authors of “The Pragmatic Programmer”) introduced  the concept of Code Kata which is a programming exercise useful to improve our knowledge and skills through practice and repetition. The interesting point of code kata is that usually the exercises proposed are easy and can be implemented on a step-by-step fashion.

Let’s do Kata togheter Daniel san!

The kata I will show you today is the FizzBuzz one. In this post we will focus only on the initial parts of stage 1: the rules can be found at Coding Dojo, but I think I will rewrite them here for the lazy ones🙂

  • write a program that prints the numbers from 1 to 100
  • for the multiples of three print “Fizz” instead of the number
  • for the multiples of five print “Buzz” instead of the number
  • for numbers which are multiples of both three and five print “FizzBuzz”

I will solve the FizzBuzz kata using TDD and this means that I will follow this pattern during my coding:

  1. write a test using Eunit
  2. run the test -> it fails
  3. write the code to make the test pass (dumb solution)
  4. run the test -> it passes
  5. refactor
  6. go to step 1

Let’s start coding then!

In this post I will write the tests and the logic inside the same file even though I know that this is not a good practice. Remember: you should never mix logic and tests in the same file. Usually what we do in Erlang is creating a test directory at the same level of ebin and src and save all our tests there, anyhow this is somehow out of the scope of this article which is about kata and I want to write this post only using one Erlang file, so forgive me for this horrible sin and let me start with our kata!

Let’s do Kata togheter Daniel san! (This time for real)

Let’s start by writing a first EUnit test where we ensure that given a number we return that number as a string:

-module(fizzbuzz).
-include_lib("eunit/include/eunit.hrl").

%% Test that given a number we return that number as a string
normal_number_test() ->
    ?assertEqual("2", evaluate(2)).

Let’s watch our test fail with pleasure now:

1> c(fizzbuzz).
{ok,fizzbuzz}
2> eunit:test(fizzbuzz).
fizzbuzz: normal_number_test (module 'fizzbuzz')...*failed*
::undef

=======================================================
  Failed: 1.  Skipped: 0.  Passed: 0.
error
3>

Rember a failing test is a good news here, because as Kent Beck says: “failure is progress”. Our first test is failing for an obvious reason: we don’t have a function evaluate/1 in our module, so we can start by coding a dumb implementation for evaluate/1 that makes our test pass.

-module(fizzbuzz).
-export([evaluate/1]).

-include_lib("eunit/include/eunit.hrl").

evaluate(_Num) ->
  "2".

%% Test that given a number we return that number as a string
normal_number_test() ->
    ?assertEqual("2", evaluate(2)).

Let’s test it:

3> c(fizzbuzz).
{ok,fizzbuzz}
4> eunit:test(fizzbuzz).
  Test passed.
ok

Success! Our test is passing, but the implementation is pretty naive. What if we focus on refactoring then? We can change the function evaluate/1 as follows:

evaluate(Num) ->
  integer_to_list(Num)

Let’s see if our test is still passing after the refactoring:

5> c(fizzbuzz).
{ok,fizzbuzz}
6> eunit:test(fizzbuzz).
  Test passed.
ok

Good job! We have our first function and it passes the test. What about adding a new functionality to our code? No wait! The real question is: what about creating a new test? Here we are:

%% Test that given a number divisible by 3 we return the string "Fizz"
divisible_by_3_test() ->
    ?assertEqual("Fizz", evaluate(3)).

Let’s recompile and test:

7> c(fizzbuzz).
{ok,fizzbuzz}
8> eunit:test(fizzbuzz).
fizzbuzz: divisible_by_3_test...*failed*
::{assertEqual_failed,[{module,fizzbuzz},
                     {line,15},
                     {expression,"evaluate ( 3 )"},
                     {expected,"Fizz"},
                     {value,"3"}]}

=======================================================
  Failed: 1.  Skipped: 0.  Passed: 1.
error

As expected the test is failing, in fact we didn’t add any new functionality to our code and therefore a failure is still a good news. Let’s make the test pass then!

This is the code you may have after implementing the aforesaid “Fizz” functionality. I believe this time we can skip a dumb solution and provide the real one as follows:

-module(fizzbuzz).
-export([evaluate/1]).

-include_lib("eunit/include/eunit.hrl").

evaluate(Num) when Num rem 3 =:= 0->
  "Fizz";

evaluate(Num) ->
  integer_to_list(Num).

%% Test that given a number we return that number as a string
normal_number_test() ->
    ?assertEqual("2", evaluate(2)).

%% Test that given a number divisible by 3 we return the string "Fizz"
divisible_by_3_test() ->
    ?assertEqual("Fizz", evaluate(3)).

Let’s now test it:

9> c(fizzbuzz).
{ok,fizzbuzz}
10> eunit:test(fizzbuzz).
  All 2 tests passed.
ok

 

Our code behaves pretty well right? At this point we should do some refactoring (of both code and tests) and then add tests and implementations for the Buzz and FizzBuzz cases. Moreover we should add a function that prints all the numbers from 1 to 100 on screen but I think I will leave all this stuff  to you as homework for a couple of reasons:

  1. I don’t like writing blog posts too long, they tend to make my readers take a nap
  2. I don’t like writing blog posts with wall of code either, they tend to make my blog uglier 
  3. I guess you may want to try solving this kata by yourself :) 

This is all I have to say about the FizzBuzz kata…or not?  Well, I can add some useful information here:

  1. Jeroen Seegers
    June 10, 2013 at 7:00 am

    http://www.reddit.com/r/dailyprogrammer is also a nice source for small kata’s for different skill levels.

  2. June 10, 2013 at 8:54 am

    Learning requires *repetition* and *time* — for mortal beings like me, at least.

    From what I gather, the concept of kata captures this first aspect of the learning process.
    What about time, then? Indeed, katas are a fascinating concept, yet it is not completely clear to me how to dovetail them with routine activities: after having spent a day staring at the screen, my mind is not fresh enough to do programming exercises!
    (am I getting old…?)

    Oh, and thank you for the reading suggestions!

    • pdincau
      June 10, 2013 at 11:57 am

      Yes, but you should keep in mind that “study” can be a part of the work routine in many companies (as in the company where I work) and kata can be done during the study.

      Oh I forgot: yes you are old Loris🙂

  3. Artem
    June 13, 2013 at 9:18 am

    But how did you manage to successfully compile fizzbuzz by the first time? I tried it and got “function evaluate/1 undefined” error.

    • pdincau
      June 13, 2013 at 4:38 pm

      the first time it obviously fails because the function is still not implemented. In this way we can prove that the tests are working.

  1. June 14, 2013 at 8:41 am
  2. September 12, 2013 at 12:11 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: