Archive for June, 2013

How to host a JavaScript coding dojo

Thursday, June 27th, 2013

Yesterday I organized a JavaScript coding dojo for my current customer’s programmers. Here’s what we did. Disclaimer: I’m not a JavaScript ninja, nor were most of the dojo participants. We need to keep it simple. We also need to make it fit within two hours.

I wanted the exercise to have a user interface. Why? Because we did many domain-only dojos, and I think we’re missing something. The UI is important: it makes the exercise more fun, and it teaches you lots. So, where to start? My starting point is the principle of domain-view separation. We want an extremely dumb UI that calls to the domain logic whenever it needs something.

My other point is that I don’t want to test the UI. We don’t have time to setup something like Selenium, and since we don’t know much JavaScript we would waste a lot of time. So we write a small UI, without tests, checking how it looks in the browser at every step. This is important: we don’t have the tests, but we have the browser to give us high-quality feedback. Also remember to keep the JavaScript console open when you do this.

The starting setup

We start from an empty exercise setup, that contains four files (not counting library files). For exercise “foo”, we have:

  • foo.html is the UI
  • foo.js contains the logic
  • foo_test.html is the test runner
  • foo_test.js contains the tests

The starting foo.html looks like this:

  
<html>
  <head>
    <title>FOO</title>    
  </head>
  <body>
    <h1>Foo!</h1>
    <script src="lib/jquery.min.js"></script>
    <script src="foo.js"></script>
    <script>
      $(document).ready(function() {
        console.log("hello");
      });
    </script>
  </body>
</html>

The starting foo.js is empty. The test runner is

<html>
  <head>
    <title>Foo Test</title>
    <link rel="stylesheet" href="lib/qunit.css">
  </head>
  <body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
    <script src="lib/jquery.min.js"></script>
    <script src="lib/qunit.js"></script>
    <script src="foo.js"></script>
    <script src="foo_test.js"></script>
  </body>
</html>  

and foo_test.js is simply

module("Foo");

test("it works", function() {
  equal(false, true);
});  

As you can see, I setup jQuery and QUnit. These are our tools.

The demo

The dojo agenda is:

  1. Introduction and demo. I solve a simpler exercise in front of the audience, with a video beamer.
  2. Explain the problem to be solved.
  3. Someone in the audience builds the UI and the first broken test.
  4. Someone else passes the test, and demonstrates that it works in the browser too! Watch out for when the tests are green and the UI is broken :) Then this person writes the next broken test.
  5. And repeat the last step until finished.
  6. Retrospective

My demo exercise was “write an application that allows me to enter a number, and prints that number doubled. Let’s call it Doubler“. The UI I built was

<html>
  <head>
    <title>doubler</title>    
  </head>
  <body>
    <h1>doubler!</h1>

    <p id="display"></p>
    <p><input type="text" name="number" value="" id="number"/></p>

    <script src="lib/jquery.min.js"></script>
    <script src="doubler.js"></script>
    <script>
      $(document).ready(function() {
        var $number = $("#number");
        var $display = $("#display");
        $number.change(function() {
          $display.html("The input is changed and its value is " + 
            $number.val());
        });
      });
    </script>
  </body>
</html>  

When I have this working I can start the TDD process. I know that all I need to do is to replace the hard-coded expression “The input … ” with a call to a domain object, like

  $display.html(new Doubler().process($number.val()));

Now I have the power of TDD at my disposal. I can make Doubler do what I want, and I know it will work in the UI. And Doubler is completely unaware that there is a UI at all; all it has to do is implement the pure domain logic. At this point, I also show how to implement an object (in the sense of object-oriented programming) in JavaScript. There are a few hundreds different ways to do that; the style I used is like this:

function Counter() {
  var itsValue = 0;
  this.increment = function() {
    itsValue++;
  }
  this.value = function() {
    return itsValue;
  }
}  

The “itsValue” local variable is accessible to the two methods (since they are closures), but is completely incapsulated and inaccessible from the outside. A test for this object could be

  test("It increments its value", function() {
    var counter = new Counter();
    counter.increment();
    counter.increment();
    equal(counter.value(), 2);
  });

After this, I proposed the team to solve stage 1 of the Tic-Tac-Toe Application Kata by Ralph Westphal. It’s simple enough to be finished in a hour, yet not trivial. One point to watch out for: we want the Game object to contain the state of the game. We don’t want to rely on the UI to tell the domain object what is the state of a given cell.

If you want a harder challenge, you could implement the Game of Life :)

Discussion

It took me a few test trials to arrive at this dojo format. I experimented with an explicit model-view-controller architecture, where you TDD also the “glue” code that I write in the UI file. This can be done by using html fixtures in the test code. But it didn’t give me the right feelings; it felt unpleasant to work with.

One thing that I surely want to avoid is the approach shown in chapter 15 “TDD and DOM Manipulation” of the (otherwise useful) Test Driven JavaScript development book. The approach in that chapter is to decide a design upfront, such as MVC, and then unit test that the controller connects itself in a certain way to the view and the model. Why I don’t like it? Because the design does not emerge from a test. Because it’s testing the implementation, not the specification. Because I want my first test to be about the valuable logic of the problem, not about a technical detail. Because I want every test to be about a valuable business behaviour.

The format I came up with feels right to me. It’s appropriate for beginners. I’m not sure that you would want to work always this way when you do production work, but it certainly is a good starting point.

Have fun!