Emil's cyber-dojo




I ran a Mastering Agile Practice tutorial with Kevlin Henney at the recent Scandinavian Developer Conference in Sweden. Emil Jönsson attended and liked Cyber-Dojo so much he ran one at his company afterwards. He says:

Just wanted to let you now that the Cyber-Dojo session I organised at work last week went really well. We did the leap year kata in Java and we were eight in total, so we ended up working in four pairs. It was fun to hear all the interesting discussions taking place and it was perfect how we could jump between the different solutions of the pairs afterwards when talking about the code. The feedback after the dojo was all positive and my colleagues liked the Cyber-Dojo way of practicing.

I hope this will become a reoccurring event. Thanks for the excellent work creating the Cyber-Dojo.

It's my pleasure Emil.


ACCU conference charity bookstall



A big thank you to the excellent people attending the ACCU 2012 conference who raised £645.77 plus a €10 note plus a very small silver coin of unknown origin! This will be split equally between Paws with a Cause and The Autism Trust.

building a rails 3 turnkey cyber-dojo server




NOTE: The cyber-dojo github repo now uses ruby(2.1.3), Rails(4) and docker(1+).
I don't think these instructions will work anymore.
Instead see setting up your own cyber-dojo docker server

I've been working on building a cyber-dojo VirtualBox Turnkey image that uses rails 3 and ruby 1.9.3 on top of the Turnkey Rails app. I figured the steps involved might be useful for someone so here they are. You can also download them as a shell file here .

First I removed the existing ruby
# cd ~
# apt-get purge ruby-enterprise
Then install libyaml
# cd ~
# wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
# tar xzf yaml-0.1.4.tar.gz
# cd yaml-0.1.4
# ./configure
# make
# make install
Then install the version of Ruby I want (this takes quite a while)
# cd ~
# wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p125.tar.gz
# tar xzf ruby-1.9.3-p125.tar.gz
# cd ruby-1.9.3-p125
# ./configure --disable-install-doc
# make
# make install
Then pull the rails3 Cyber-Dojo source (hit return when it asks for a password). I got some utf-ascii conversion warnings which don't seem to matter. When asked if I wanted to overwrite an executable I responded [y]es. This too takes quite a while.
# cd /var/www
# git clone https://JonJagger@github.com/JonJagger/cyberdojo
# chown -R www-data cyberdojo
# chgrp -R www-data cyberdojo
# cd cyberdojo
# gem update --system
# gem update --no-rdoc
# gem install bundle --no-ri --no-rdoc
# bundle install
Then setup apache
# cd /etc/apache2/sites-enabled
# sed s/railsapp/cyberdojo/ <railsapp >cyberdojo
# rm railsapp
# cd /etc/apache2/sites-available
# sed s/railsapp/cyberdojo/ <railsapp >cyberdojo
# rm railsapp
# cd /etc/apache2/conf
# sed s/railsapp/cyberdojo/ <railsapp.conf >cyberdojo.conf
# rm railsapp.conf
Then setup passenger (it takes quite a while), and edit /etc/apache2/conf.d/passenger as directed by the output
# cd ~
# apt-get update
# apt-get install libcurl4-openssl-dev
# cd /var/www/cyberdojo
# gem install passenger --no-ri --no-rdoc
# passenger-install-apache2-module
Then
# cd /var/www/cyberdojo
# service apache2 restart
And viola, cyber-dojo was up. Saving to a .ova file creates a 418MB file. This will give you C and C++ (gcc 4.4.5), Perl (5.10.1), Python (2.6.6), Ruby (1.9.3). If you want to upgrade any of these or use any of the other languages you'll need to install their compilers and unit test frameworks.

cyber-dojo Skillsmatter podcast

I had the pleasure of running a Cyber-Dojo at Skillsmatter's 2 day Progressive Java tutorial last week. The session was video'd and is available here.

requiem for C head cam

At the ACCU 2012 conference Uncle Bob gave his excellent keynote Requiem for C. Skillsmatter video'd the whole keynote and it will be available soon. As an experiment Uncle Bob gamely agreed to wear a Go Pro 2 head camera whilst giving the keynote! So here, possibly for the first time ever, are a few rough clips of what it's like to give a keynote.





The evolution of useful things


is an excellent book by Henry Petroski (isbn 0-679-74039-2). As usual I'm going to quote from a few pages:
Can any single theory explain the shape of a Western saw, which cuts on the push stroke, as readily as an Eastern one, which cuts on the pull?
A French book of advice to students recognised the implicit threat involved in using a weapon at the table, and instructed its readers to place the sharp edge of their knife facing towards themselves… Such actions, coupled with the growing widespread use of forks, gave the table knife its now familiar blunt-tipped blade.
Round chopsticks would tend to twist in the fingers and roll off the table, and so squaring one end eliminated two annoyances in what is certainly a brilliant design.
The stories associated with knives, forks, and spoons also illustrate well how interrelated are technology and culture generally.
Luxury, rather than necessity, is the mother of invention.
The very properties of the material that make it possible to be shaped into a useful object also limit its use.
Engineering is invention institutionalised, and engineers engaged in design are inventors who are daily looking for ways to overcome the limitations of what already works.
It is not the form follows function but, rather, that the form of one thing follows from the failure of another thing to function as we would like.
When sewn into a garment, a piece of thread can be thought of as a continuous and flexible ghost of a needle.
It is 3M's policy (and that of other enlightened companies) to allow its engineers to spend a certain percentage of their work time on projects of their own choosing, a practice known as "bootlegging".

Consilience


is an excellent book by Edward O. Wilson (isbn 0-349-11112-X). As usual I'm going to quote from a few pages:
The first step to wisdom, as the Chinese say, is getting things by their right names.
The cost of scientific advance is the humbling recognition that reality was not constructed to be easily grasped by the human mind.
Analysis and synthesis, he [Goethe] liked to say, should be alternated as naturally as breathing in and breathing out.
Nothing in science - nothing in life, for that matter - makes sense without theory.
Complexity is what interests scientists in the end, not simplicity.
Consilience among the biological sciences is based on a thorough understanding of scale in time and space.
Complexity theory can be defined as the search for algorithms used in nature that display common features across many levels of organisation.
In a system containing perfect internal order, such as a crystal, there can be no further change.
The brain is a machine assembled not to understand itself, but to survive.
The biologist S. J. Singer has drily expressed the matter thus: I link, therefore I am.
No example of bias-free mental development has yet been discovered.

Curry velocity

Some people's introduction to curry begins with them ordering the hottest dish on the menu. They discover the dish is beyond their curry-capacity and they can't finish it. Amazingly, they often repeat this behaviour. Lots of curry goes to waste. Dishes are frequently only half-eaten. Curry velocity remains at zero.

Other people's introduction to curry begins with them trying something nearer the cooler end of the Scoville scale. They find the dish is below their curry-capacity. They finish it! No curry is wasted. Their curry velocity is above zero. The next time they may decide to try something a little hotter. But they are in control of the curry, rather than the curry being in control of them.

Being wrong

is an excellent book by Kathryn Schulz (isbn 978-0-06-117604-3). As usual I'm going to quote from a few pages:
One extremely good way to become wedded to a theory you just idly expressed is to have it contradicted... from noncommittal to evangelical in a matter of milliseconds.
We take our own certainty as an indicator of accuracy.
The instant an implicit assumption is violated, it turns into an explicit one.
When we ask people to look for something specific they develop a startling inability to see things in general.
The genius of statistics was that it did not ignore errors, it quantified them. [Laplace]
In ancient Indo-European, the ancestral language of nearly half of today's global population, the word 'er' meant "to move", "to set in motion", or simply "to go."
It is all too common for caterpillars to become butterflies and then maintain that in their youth they had been little butterflies.
the stakes of our mistakes.
Realizing that we are wrong about a belief almost always involves acquiring a replacement belief at the same time.
"fallor ergo sum" (I err, therefore I am) [St Augustine]
When other people reject our beliefs, we think they lack good information. When we reject their beliefs, we think we possess good judgement.
As with so many systems, the strengths of inductive reasoning are also its weaknesses. For every way that induction serves us admirably, it also creates a series of predictable biases in the way we think...
When a framework serves us well... we call it brilliant, and call it inductive reasoning. When it serves us poorly, we call it idiotic, and call it confirmation bias.
Being wrong can be funny; other people being wrong can be very very funny.
Without some kind of belief system in place, we wouldn't even know what kinds of questions to ask, let alone how to make sense of the answers.

Adapt - why success always starts with failure

is an excellent book by Tim Harford (isbn 978-0-349-12151-2). As usual I'm going to quote from a few pages:
Cross the river by feeling for stones [Deng Xiaoping]
Accepting trial and error means accepting error.
Darwin, a meticulous observer...
The art of success is to fail productively.
Complexity is a problem only in tightly coupled systems.
Make sure you know when you've failed, or you will never learn.
What Palchinsky realised was that most real-world problems are more complex than we think. They have a human dimension, a local dimension, and are likely to change as circumstances change. His method for dealing with this could be summarised as three 'Palchinsky principles'
  • seek out new ideas and try new things
  • when trying something new, do it on a scale where failure is survivable
  • seek out feedback and learn from your mistakes as you go along
If we are to take the 'variation' part of 'variation and selection' seriously, uniformly high standards are not only impossible but undesirable.
When John Nagl served in Baghdad in 2003, he found that while his young inexperienced soldiers had the authority to kill, he - a major with a doctorate and a decade of experience - didn't have the authority to print his own propaganda pamphlets to counteract the clever PR campaign that the local insurgents were running.
Speciation - the divergence of one species into two separate populations - rarely happens without some form of physical separation.
Tight coupling means the unintended consequences proliferate so quickly that it is impossible to adapt to the failure or to try something different.
The first thing Timpson does when it buys another business is to rip out the electronic point-of-sale machines (there are always EPOS machines) and replace them with old fashioned cash registers. 'EPOS lets people at head office run the business', explains John Timpson. 'I don't want them to run the business.'

John Timpson describes one instance where he couldn't buy half-price happy hour drinks at a hotel bar, because midway through giving his order, the hour ended and the bar's computerised sales system refused to allow the half-price offer to be applied.

Timpson's company training manual describes the twenty easiest ways to defraud the company, making it clear that the company understands the risks it is running and trusts its employees anyway - and many people respond to being trusted by becoming more trustworthy.
A central point of the corporation, as a legal structure, is that it is supposed to be a safe space in which to fail. Limited liability companies were developed to encourage people to experiment, to innovate, to adapt - safe in the knowledge that if their venture collapsed, it would merely be the abstract legal entity that was ruined, not them personally.
Fail better. [Samuel Beckett]

The conquest of happiness

is an excellent book by Bertrand Russell (isbn 0415378478). As usual I'm going to quote from a few pages:
It will be found that a quiet life is characteristic of great men, and that their pleasures have not been of the sort that would look exciting to the outward eye. No great achievement is possible without persistent work.
Worry is a form of fear, and all forms of fear produce fatigue.

Every kind of fear grows worse by not being looked at.
More and more it becomes possible to choose our companions on account of congeniality rather than on account of mere propinquity.
Like the heroes of Valhalla who spent every day hunting a certain wild boar, which they killed every evening but which miraculously came to life again in the morning…
Fundamental happiness depends more than anything else upon what may be called a friendly interest in persons and things.

To like many people spontaneously and without effort is perhaps the greatest of all sources of personal happiness.

The secret of happiness is this: let your interests be as wide as possible, and let your reactions to the things and persons that interest you be as far as possible friendly rather than hostile.
The more things a man is interested in, the more opportunities of happiness he has.
Events only become experiences through the interest that we take in them.
In the best kind of affection a man hopes for a new happiness rather than for escape from an old unhappiness.
Work, therefore, is desirable, first and foremost, as a preventive of boredom, for the boredom that a man feels when he is doing necessary though uninteresting work is as nothing in comparison with the boredom that he feels when he has nothing to do with his days.
Two chief elements make work interesting: first, the exercise of skill, and second, construction.

All skilled work can be pleasurable, provided the skill required is either variable or capable of indefinite improvement.
We may distinguish construction from destruction by the following criterion. In construction the initial stage of affairs is comparatively haphazard, while the final state of affairs embodies a purpose; in destruction the reverse is the case: the initial state of affairs embodies a purpose, while the final state of affairs is haphazard.
Destruction is of course necessary very often as a preliminary to subsequent construction; in that case it is part of a whole which is constructive.
Few things are so likely to cure the habit of hatred as the opportunity to do constructive work of an important kind.
I should seek to make young people vividly aware of the past, vividly realising that the future of man will in all likelihood be immeasurably longer than his past, profoundly conscious of the minuteness of the planet upon which we live and of the fact that life on this planet is only a temporary incident; and at the same time with these facts which tend to emphasise the insignificance of the individual I should present quite another set of facts designed to impress upon the mind of the young the greatness of which the individual is capable, and the knowledge that throughout all the depths of stellar space nothing of equal value is known to us.
Happiness must be, for most men and women, an achievement rather than a gift of the gods, and in this achievement effort, both inward and outward, must play a great part.
The only man totally indifferent to power is the man totally indifferent to his fellow-men.
It is better to do nothing than to do harm. Half the useful work in the world consists of combating the harmful work.

smell-driven development

After much research by our scientists I can finally report a major advance in software methodology - smell driven development.

Our scientists have perfected a set of software metrics which accurately monitor the health of your software. These metrics are gathered in real time by our patented custom SmellWare servers. Each SmellWare server (prices to be announced shortly) is connected via USB to three glass vials and a sophisticated spray-atomizer.
  • When the metrics read by the SmellWare server indicate your software is in a poor state, the atomizer will spray scent from the first glass vial.
  • When the metrics indicate a further deterioration, the atomizer will spray scent from the second glass vial.
  • When the metrics indicate a really disgusting codebase, the atomizer will spray scent from the third glass vial.
By choosing smells with an increasing tendency to get on the developers' olfactory nerves you can "visualize" the state of your codebase in a way that cannot be ignored!

The genius of this approach is that smell, being the oldest sense, has had the longest to evolve. The olfactory sense is, at the same time, both the most primitive sense and the most sophisticated. Even in humans about 1 in 50 genes is devoted to smell-related protein receptors!

Our odour scientists have studied the four aspects of threshold and tolerance; odour concentration, odour intensity, odour quality, and hedonic tone, and after extensive field testing the first (cheese based) vials are ready.
  • Vial 1 (Yellow) is based on Pong-Leveque (Normandy) and is ranked "distinct, strong, and unpleasant" on the Odour Awareness scale.
  • Vial 2 (Amber) is based on Epoisses de Pieds (Southern Italy) and is ranked "very strong, liable to cause rashes and sore eyes". (Epoisses de Pieds is banned from public transport in Italy).
  • Vial 3 (Red) is based on Peixe-Podre et Meia (Northern Portugal) and is ranked "intolerable, liable to cause vomiting, diahorrea, and heart attacks". (Peixe-Podre et Meia is based on Blue-vein Smegma which had a 97% mortality rate before the EU made its manufacture a federal offense punishable by 25 years imprisonment.)
Believe us when we tell you that once your developers have experienced Peixe-Podre et Meia (Red) they will never again sit idly by while your codebase is merely in Epoisses de Pieds (Amber) state!

Ivan Marks - the people's champion

is an excellent book from Media Press (isbn 978-0-9567015-9-6). As usual I'm going to quote from a few pages:
Young anglers were encouraged and taught the basic skills by more experienced anglers. The club would fish matches where novice anglers were paired off with the top men. For two hours the older angler sat patiently with his pupil explaining the correct tactics to use.
There are, of course, times of the year when the facility to make maggots sink at a reduced rate of fall is a great advantage, especially in still water.
A 4lb chub will eat a half-pint of casters.
His [Benny Ashurst] maxim was always to keep the fish feeding for as long as you can.
Tanked fish have been fed yellow maggots and given an electric shock every time the made a move to eat one. The same fish were fed white maggots and allowed to take what they liked without interference. Later, when those same fish were fed mixed yellow and whites they wouldn't look at the yellows - and can you blame them? That experiment proves that fish can learn.
The real secret with loose-feeding is regularity.
You must not panic and fool yourself into believing that the more stuff you throw in, the more fish will come out.
I told the Italian team manager that I might have taken the individual honours had I been able to stay catching bleak of around that weight. "No Ivan," said the Italian, "it isn't possible!" He explained that my 1oz bleak was a fat and none too healthy fish, and he was right. It looked spawn-bound. In fact he said it had a worm infection. And he explained that fish in that condition are not fit fish. They don't move to the bait fast enough - even if there are enough of them - to allow true speed fishing. Which helps explain just how deeply the Italians have delved into this type of fishing.
A barbless hook punctures the bait, but fills the hole it makes.
Roach and bream don't grab your bait with their teeth. They simply inhale water into their mouths and this sucking process puts the bait where you want it to go.
The biggest risk of breaking a line comes from shock impact. Sudden shock is to be avoided at all costs.

Fun and learning at Ericsson

I had the pleasure of teaching a TDD C++ course at Ericsson's Jorvas centre in Helsinki this week. As usual I made heavy use of cyber-dojo. Above is a screen shot of the dashboard of one of the practice katas. My evals were 5.8 for the course as a whole and 5.9 for teaching skills (out of 6). Some of the comments were:
  • Very clear.
  • You really got us understanding TDD.
  • Transformation of the mindset became clearly visible during the course.
  • Thanks!
  • Best course I've taken at Ericsson, thank you.
  • The cyberdojo is an excellent environment.
  • Very good hands on training.
  • cyber-dojo extremely nice.
  • It was fun!
  • You really need to try to do TDD in practice to see how beneficial and fun it is.
  • You made it visible in practice.
  • Fun fun fun.

Nicer HTML radio buttons

One of my pet peeves is plain html radio buttons. If I have a set of 5 radio buttons with 5 text labels of differing lengths then I want to be able to click anywhere on the shaded area and not just the text labels.

This is quite easy to achieve. Simply put each <input> into a <div>...
<div class="radio">
  <input type="radio" ... value="Red"/>
    <label>Red</label>
</div>
<div class="radio">
  <input type="radio" ... value="Amber"/>
    <label>Amber</label>
</div>
<div class="radio">
  <input type="radio" ... value="Green"/>
    <label>Green</label>
</div>
...and use a bit of jQuery
var $j = jQuery.noConflict();
$j(document).ready(function() {
  $j('div.Radio').each(function(n,node) {
    $j(node).click(function() {
      $j(this).children(':first').attr('checked', true);
    });
  });
});
Using a <div> changes the layout - so you might want to put each <div> into a table layout.

You can add some CSS to highlight the clickable whitespace...
  .Radio { background-color: Moccasin; }
  .Radio::after { content: "\00a0"; }
If you want to remove the bullet simply add the following
$j(document).ready(function() {
  $j('input[type=radio]').hide();
};
If you want to see an example of this, just try CyberDojo

Complexity and postmodernism - understanding complex systems

is an excellent book by Paul Cilliers (isbn 0-415-15287-9). As usual I'm going to quote from a few pages:
Complex systems operate under conditions far from equilibrium. There has to be a constant flow of energy to maintain the organisation of the system and to ensure its survival.
If resources were limitless, i.e., if growth could take place unrestricted, no meaningful structure would evolve. Boundaries, limits and constraints are preconditions for structure.
The theory of self-organised criticality tells us the following. A self-organising system will try to balance itself and a critical point between rigid order and chaos.
The classic definition of stability states that in a stable system small causes produce small effects.
The classical definition of instability, at least as used by Poincaré, is probabilistic. Unstable events are defined as events that have no observable cause.
The system of language transcends the choices of any individual user, and therefore has stability.
In the last analysis, the two facts are interdependent: the sign is exposed to alteration because it perpetuates itself.
When dealing with complex phenomena, no single method will yield the whole truth.

Bare bones ruby unit testing

This morning I spent a happy hour exploring a little of ruby's Test::Unit::TestCase. I started with this:
require 'test/unit'

class MyTest < Test::Unit::TestCase

  def test_one_plus_one_equals_two
    assert_equal 2, 1+1.1
  end

end
I wanted to see how little I needed to write my own, super-minimal implementation of Test::Unit::TestCase...
require 'test/unit'

class MyTest < MyTestCase

  def test_one_plus_one_equals_two
    assert_equal 2, 1+1.1
  end

end
After 204 traffic lights in cyber-dojo I ended up with this...
require 'assertion_failed_error'

class MyTestCase

  def self.test_names
    public_instance_methods.select{|name| name =~ /^test_/}
  end
  
  def assert_equal( expected, actual )
    message = 
      "#{expected.inspect} expected but was\n" +
      "#{actual.inspect}\n"
    assert_block(message) { expected == actual }
  end

  def assert_block( message )
    if (! yield)
      raise AssertionFailedError.new(message.to_s)
    end
  end

end

at_exit do
  ::ObjectSpace.each_object(Class) do |klass|
    if (klass < MyTestCase)
      klass.test_names.each do |method_name| 
        begin
          klass.new.send method_name
        rescue AssertionFailedError => error
          print "#{klass.name}:#{method_name}:\n" +
                "#{error.message}"
        end
      end
    end
  end
end
class AssertionFailedError < RuntimeError; end
which allowed me write...
require 'my_test_case'

class MyTest < MyTestCase

  def test_one_plus_one_equals_two
    assert_equal 2, 1+1.1
  end

end
and finally, I added this...
class MyTestCase
  ...
  def self.test( name, &block )
    define_method("test_#{name}".to_sym, &block)
  end
  ...
end
which allowed me to rewrite the test as...
require 'my_test_case'

class MyTest < MyTestCase

  test "1+1 == 2" do
    assert_equal 2, 1+1.1
  end

end
Fun :-)

The Vizzini school of bad management

  • Am I going mad or did the word "think" escape your lips?
  • Hurry up
  • Inconceivable
  • Faster!
  • You know what a hurry we're in
  • I'm waiting!
  • Catch up with us quickly
  • I do not accept excuses
  • Did I make it clear that your job is on the line?
  • There will be no one to hear you scream
  • Stop doing that. We can relax, it's almost over


renaming a sub-directory with a space in it in git

Suppose you have a git sub-directory with a space in it...
/outer/old name/
It appears you cannot rename the sub-directory with a space in it to a different name which also has a space in it. For example, the following does not work...
git mv -f "outer/old name/" "outer/new name/"
However, after much trial and error, I have found the following which does work...
git mv -f "outer/old name/" "outer/temp-name/"
git commit -m "rename subfolder with space part 1/2"
git mv -f "outer/temp-name/" "outer/new name/"
git commit -m "rename subfolder with space part 2/2"
Hope this proves useful to someone.

my kanban 1's board game

Here's a slide deck explaining the essence of my kanban 1s board game. Jon Jaggers Kanban 1s Board Game
  • You can play an early session with no clips so the players can see how inventory builds up (you can also push done story-cards to the next edge's corner, rather than waiting for them to be pulled).
  • The clips that hold the story-cards are a crucial part of the game. They make it a kanban game.
  • You can limit the number of clips per edge to create a natural work-in-progress (wip) limit.
  • You can add a new rule: players can also spend a 1 to split a story-card in two, eg a 4 into a 3 and a 1 (assuming they have a spare clip).
  • You can record the day a story-card comes off the backlog, and also the day it gets to done and thus measure the cycle time.
  • You can simulate scrum-style discrete sprints.
  • You can vary the number of dice at different edges.