January 2009

Saving Bletchley Park

> Bletchley Park, the codebreaking centre that helped to win the Second World War and launch the modern computer, is in danger of irreparable decay unless the Government steps in to save it.

What can you do?

Uncategorized

Comments (0)

Permalink

Acceptance Tests Trump Unit Tests

At work, we have been practising something approximating Acceptance Test Driven Development now for several months. This means that pretty much every feature of the system that a user would expect to be there, has an automated test to ensure that it really is.

It has given me a whole new perspective on the value of tests as artefacts produced by a project.

I made a pledge to myself when I started this new job in August that I would not (knowingly) check in a single line of code that wasn’t driven out by a failing test. At the time, I thought this would always mean a failing unit test, but I’m starting to see that this isn’t always necessary, or in fact even wise.

Don’t get me wrong. Unit testing is extremely important, and there’s no doubt that practising TDD helps you to write well-structured, low-defect code in an really satisfying manner. But I do feel like the extent to which TDD, at the level of unit testing alone, allows for subsequent changes to the behaviour of the code, has been oversold.

If you think you’re doing TDD, and you’re only writing unit tests, I think you’re doing it wrong.

As new requirements come in, the tensions influencing the design of the code shift. Refactoring eases these tensions, but by definition means that the design has to change. This almost certainly means that some, often significant, portion of the unit tests around that area of the code will have to change too.

I struggled with this for a long time. I had worked hard on those tests, for one thing, and was intuitively resistant to letting go of them. More than that, I knew that somewhere in there, they were testing behaviour that I wanted to preserve: if I threw them out, how would I know it still worked?

Yet those old unit tests were so coupled to the old design that I wanted to change…

Gulliver

In my mind, I have started to picture the tests we write to drive out a system like little strings, each one pulling at the code in a slightly different direction. The sum total of these tensions is, hopefully, the system we want right now.

While these strings are useful to make sure the code doesn’t fall loose and do something unexpected, they can sometimes mean that the code, like Gulliver in the picture above, is to restrained and inflexible to change.

The promise of writing automated tests up front is regression confidence: if every change to the system is covered by a test, then it’s impossible to accidentally reverse that change without being alerted by a failing test. Yet how often do unit tests really give us regression alerts, compared to the number of times they whinge an whine when we simply refactor the design without altering the behaviour at all? Worse still, how often do they fail to let us know when the mocks or stubs for one unit fail to accurately simulate the actual behaviour of that unit?

Enter acceptance tests.

By working at a higher level, acceptance tests give you a number of advantages over unit tests:

  • You get a much larger level of coverage per test
  • You get more space within which to refactor
  • You will test through layers to ensure they integrate correctly
  • They remain valuable even as underlying implementation technology changes

Admittedly, the larger level of coverage per test has a downside: When you get a regression failure, the signpost to the point of failure isn’t as clear. This is where unit tests come in: if you haven’t written any at all yet, you can use something like the saff squeeze to isolate the fault and cover it with a new test.

They’re also much slower to run, which can be important when you’re iterating quickly over changes to a specific part of the system.

To be clear, I’m not advocating that you stop unit testing altogether. I do feel there’s a better balance to strike, though, than forcing yourself to get 100% coverage from unit tests alone. They’re not always the most appropriate tool for the job.

To go back to the metaphor of the pulling strings, I think of acceptance tests as sturdy ropes, anchoring the system to the real world. While sometimes the little strings will need to be cut in order to facilitate a refactoring, the acceptance tests live on.

The main thing is to have the assurance that if you accidentally regress the behaviour of the system, something will let you know. As long as every change you make is driven out by some kind of automated test, be it at the system level or the unit level, I think you’re on the right track.

Agile / Lean Software Development

Comments (2)

Permalink

Quick and Easy Password-less SSH Login on Remote Servers

Like so many posts in this category, this is surely child’s play to you linux aficionados. For those of us mere morals though, this is a very useful little trick, and it shows how you can easily move data from your local workstation to a remote server using SSH.

If you don’t already have a public / private key pair on your local workstation do this:

ssh-keygen -t rsa

If you have no idea what I’m talking about, try looking for this:

ls ~/.ssh

Did you see anything? You’re looking for a file called id_rsa.pub, I would guess.

Now that you have generated your key, to copy the public key part up to the remote server, do this:

ssh remote-user@remote-server.com “echo ‘cat ~/.ssh/id_rsa.pub‘ >> ~/.ssh/authorized_keys”

You should now be able to dance around the inner bits of the internet to your heart’s content.

Thanks to Dan Lucraft for the technology behind this post.

Linux / OS X Newbie Tips

Comments (1)

Permalink

MagLev: Death of the Relational Database?

I just got around to watching Avi Bryant’s talk on MagLev, a new Ruby VM built on top of GemStone’s Smalltalk VM.

http://www.vimeo.com/1147409

Presumably this is the kind of thing Smalltalkers have been able to do for decades, but to me the prospect of having this kind of freedom on a Ruby platform is very exciting. Terrific stuff. I wonder what performance is like.

Agile / Lean Software Development
Ruby Programming

Comments (0)

Permalink

Minesweeper Dojo

This evening I facilitated our first coding dojo at work. I’d spent some time over the holidays putting together a progression of Cucumber acceptance test cases to build up the solution, and had solved the problem once myself.

I used the minesweeper kata from http://codingdojo.org/ which was a really nice easy problem for our first dojo I think.

Format

Executive summary:

  • Randoori format
  • 6 programmers (plus me, facilitating)
  • 2 hours.
  • 10 minute iterations
  • 10 minute retrospective at the end.

I was clear at the start to point out that it was rude and disruptive for the crowd to criticise design when tests were failing, but that once tests were green, we would have a design review and do some re-factoring.

In fact, as we got into it, we began stopping the clock for design discussions (though perhaps these could also be timeboxed to keep the urgency up) so that people got a fair chance at the keyboard, but we also got plenty of time to analyse the design.

Summary

I held a little retrospective at the end where we collected some thoughts, then a few of us went for a pint afterwards and talked about it some more.

Good points:

  • Most people seemed to enjoy working on a ‘toy problem’:
    • everyone had worked on it equally so design discussions were never personal
    • we could really focus on getting the best solution to the problem, because it was so simple
  • Doing it out of hours meant we could really relax and have fun with it
  • It was a great way to get the team to rapidly build consensus about conventions and coding style
  • Having flog stats in the rake task made the final re-factoring stage much more worthwhile and fun

Bad points:

  • Some people found the problem too easy to solve, meaning we spent a fair amount of the session ‘polishing’ a working solution
  • I forgot to reset the stopwatch sometimes, which meant things got stale
  • There was a tendency for people to just rotate in / out in order which meant you kept getting the same combinations of pairs In the end I started drawing them out of a hat
  • We suck at git, particularly moving files from one branch to another
  • We suck at understanding flog’s feedback very well

Ideas for next time:

  • Find a way to visualise the changing Flog scores between commits
  • Try other programming languages
  • Need to mix up the type of kata: some people would prefer doing things they’d find more challenging, like a tough re-factoring
  • Get some food and beer in
  • Try shorter iterations?
    • In fact, try short / long pairs and see which we prefer!

I tend to perfectionism, so I really enjoyed the last half hour where we just re-factored the right-but-ugly first solution to the problem, extracting methods and classes and moving code around, ironing out the wrinkles and getting the flog / reek scores down. I enjoyed the discussions as we traded off different design principles and weighed up the appropriate route to take. Some people definitely found this time less rewarding, but I wonder whether they rather missed the point: this isn’t about solving a tough problem – we do that all day – this is about solving a simple problem the right way so that next time we hit one of those tough problems, we might be able to solve it a little more elegantly.

Legacy

I put the git repository where we worked on the problem up on gihub here:

http://github.com/mattwynne/software-craftsmanship-katas/tree/master/minesweeper

I would be stoked if anyone forked the repo and pushed their own solution. How low can you get your flog scores?

Agile / Lean Software Development

Comments (3)

Permalink