Extreme Lego Workshop

I was lucky enough to attend an Extreme Lego Workshop last week. It was a three-hour session to give teams the feel of doing XP. It’s designed for members of a delivery team (developers and managers) who are interested in experiencing the XP process first-hand.The advantage of using Lego MindStorms over something like J2EE, .NET or SmallTalk is the learning curve is very small and it minimises the variation of expertise and suited timescales nicely.

We were split into two competing teams. Each team had a customer (the guys running the workshop) and a delivery team of six - two software developers (pair-programming the brick), three hardware guys (triplet-building Lego) and one tracker (coordinating it all).

Every twenty-minutes or so we’d rotate roles so we all got a chance to try everything. There were three objectives. - To deliver a product. - To experience the practices of XP. - To have fun.

Here;s how the session panned out.

Introduction

Firstly we were introduced to the course and XP and told that we’re going to build some robots to compete in a racing tournament. The details were very vague and we were going to have to make estimates for how long each feature would take. Most of us were unfamiliar with developing MindStorms robots and had no idea how it all worked, so without further ado we were sent on a Spike.

Spike Solution

A spike solution is used in XP when developers have to estimate something they know nothing about, typically used when a new technology is introduced. The idea is you spend a very short amount of time experimenting and getting a feel for whatever you’re supposed to be doing. In that time you throw things like unit-tests out the window and just hack in pairs.

When you’re done you throw everything away and walk out with nothing to show other than your knowledge.

I sat on the software team and paired with the only person who knew how to program MindStorms. We quickly raced through the software, conditional logic, events, the various sensors and motors, saving/loading, downloading to the brick, etc. Meanwhile the other team members were rummaging through the box of Lego playing with the blocks, sensors, wheels and cogs.

In no time at all (I think it lasted half an hour) our spike was over. In what seemed like a short period of chaos, we’d actually learned a lot. Between us we now had an idea of what was possible and how to achieve it. The not so obvious thing was that in that time, we had started to gel as a team.

Iteration One - The Planning Game

The first iteration of our project began. Each iteration was to last one hour.

The customer came forward with four stories they needed implemented. Some of these were complicated like being able to follow a line around a course or count how many beans it drove over. The customer stated that it was really important to be able to compete in the dragster race by the end of iteration one. This meant the robot should speed as fast as it could down a straight track until it drove over the finish line.

We examined the stories and started breaking them down into tasks. To create a dragster the most obvious thing was to build a robot that just drove forward. For that we’d need wheels attached to a motor, connections to the control brick, a chassis to hold it all together and some software to turn the motor on at the highest speed. To estimate how long that would take, we had to combine our previous development experiences with what we’d learnt on the spike. We also had to trust each other’s judgement because we had all learned different things on the spike. We repeated this for a few more tasks.

Soon we realised we only had forty minutes left of our iteration and the estimates we had already totalled more than that so we finished up the planning game and went into implementation mode.

Iteration One - Implementation

We rotated roles. I was left on software now as the newborn software expert it was lucky I had paired with someone on the spike so I knew how it all worked. My new partner rotated in (Alistair Cockburn) and we figured out what we needed to do. I spent a couple of minutes taking Alistair through the basics of the software so he was up to speed on it and we began planning our software.

We had a simple task to make the motor drive forwards but very soon we realised we had a problem - which way was forwards?

We asked the tracker who got the attention of the hardware guys. The hardware guys told us which way round the controller brick and motors would face and how the wires were connecting them. We quickly drew up a diagram on a scrap of paper and stuck it to the wall for all to see. The software team and hardware team each had their own controller brick so we could test things in parallel.

Our customer wandered over all excited about the amount of work he could see going on and asked if he could see anything yet. We showed him our software program and a single wheel spinning on our test brick. This wasn’t what he wanted to see - he wanted to see a dragster. He wanted to see a dragster and we showed him a spinning wheel!. But the hardware team had already built a full chassis with four wheels. With very little effort we could integrate our work and show him a working dragster. And we did. And it worked. And he liked it.

But there was a problem; the robot didn’t stop when it crossed the finishing line. The customer said this was very important, as for every extra cm they would be penalised by the race rules. We didn’t know that and quickly turned our focus on to that.By this point we were half way through the iteration and I rotated onto the hardware team for the first time. The hardware guys had a nice little system going where two people would work on building the robot and the other forested for the little Lego parts. The forester would pre-empt what the builders needed and have the parts already waiting.

I went straight into building, as my fingers are small and nimble. Very quickly I was working with someone who I already knew from working on the spike and we coordinated our four hands precisely to the robot speedily. As we went on I picked up the other tricks the hardware team had learned such as which wheels were most appropriate and how to fix them on properly so they didn’t destroy the system at high speeds.

We had one task: to fix the light sensor on the front of the vehicle to allow the software to detect when we’d passed the finish line. To achieve that we had to dismantle the front of the robot.

As we were going, we realised a flaw in our design: our robot was designed to be a dragster and was very long. One of the stories the customer had also asked for (although currently un-prioritised) was for our robot to follow a line around a course. Our robot couldn’t deal with corners with such a long body and fixed axels, so we decided to spend some time making it able to handle corners. We spent more time than we hoped on this but we eventually got there.

Meanwhile the software team had been experimenting with the light sensor and realised it was trickier than anticipated as we had to take into account different levels of light and reflection.There were five minutes left of the iteration which we spent integrating it all together.

Racing - Part One

This was our first glimpse of the other team’s robot. It looked like a very simplified version of ours. Had we over-engineered ours or was theirs not up for the job?

We raced and it was immediately obvious that both teams had the same bug in their software - the motor cut out when it went over the thick black finishing line but the momentum carried it forward until it reached the end of the line where the motor then fired up again and continued until the track stopped.

The race time was nearly identical, however, because ours had more parts the weight carried it further passed the end of the track, which we were penalised for.

Iteration Two

The second (and last) planning game begun.

The customer shifted priorities around a bit and said that he’d just found out that there were more points to be gained in the race where the robot is to race forward until it hits a wall then reverse back to the start line.

Oh yeah, it was important that the same robot competed in both races although we could switch programs. So we prioritised this and threw around some ideas.: - Some springy parts would make a nice bumper way out in front of the robot to detect the wall and absorb the impact. - We could mount this on the back of our existing robot and drive it in reverse for the second race as we already had a light sensor that would help us detect the finish line of both races.

We split the task into stories and then kept falling into the trap of deciding how to implement each task - we shouldn;t be doing that in the planning game.

Time was ticking so we jumped into implementation.We did some building for a while and someone had a brilliant idea of using the same program for both races. All we had to do was give our robot a little bump at the beginning of the dragster race and it would think it had hit the wall and quickly reverse over the finishing line

Soon it was time to rotate again and I was back on the software. The code was getting a little messy so we took a couple of minutes to explore if there was anything in the bundled tools to make our life easier. Sure enough there was and we managed to refactor an ugly looking program into something very small and simple.

The software tasks for the current story were done half way through the iteration but the hardware guys still had a lot of work to do on the bumper. Even though we had loads of time left we decided to try and integrate.Disaster! The brick of the real robot had dead batteries. We had to dismantle the thing to replace the brick with our good brick. This was tricky but we eventually got there. We tested our software and it didn’t work.

Now it was getting tricky because we had to fix the software but we;d lost our test brick. Trying to modify the software with only one brick stopped the hardware guys from doing their job and vice-versa so we ran around for a bit until we found some new batteries.

Back to the problem - why didn’t the software work? It worked before (shame we didn’t have unit-tests). After much experimenting we realised we had the light tolerance of the sensor wrong and it thought it was always over the finishing line. Through trial and error we managed to fix this.

Suddenly there were two minutes left of the iteration and we didn’t have a working robot.

We scrambled around and integrated the software. It worked with just twenty seconds to go.

Wait a minute - no it didn’t! The wheels were driving the wrong way! We quickly modified the software and managed to get it reintegrated - we did a manual test and the system was fine. Time was up.

Racing - Part Two

The moment of truth had arrived. We now had a chance for the rematch of the dragster race and our chance to prove ourselves in the bumper race.

The other team were first up.

Marks, set, go… dead battery.

While they swapped their brick around, we took our mark on the start line.

Go!

Our dragster speeded away - it seemed much faster than before. It crossed the finish line in record time. Except it didn’t acknowledge the finish line, even though we’d refactored the software to do so this time. And it didn’t acknowledge the end of the track. It sailed off over the carpet into the sunset (until it hit a wall).

The other teams dragster took the line and did a perfect race.

Now it was time for the second race where we were to bump into a wall. I was nervous about this - we needed a huge time advantage to beat the others in overall points and if our software had gone so wrong for the trivial tasks, what would it do for this?

Off it went went. I couldn’t watch. The heavy and still slightly flimsy dragster was hurtling full speed towards a solid wall. The springy bumper hit first, sent the wheels into reverse gear before the rest of it caught up. The combination of the fat bumper and the reversing wheels beautifully absorbed the momentum and it went tearing back down the track and over the line. Unfortunately it didn’t stop again but as it brushed against my strategically placed foot it somehow stopped.

It was a brilliant run, but could the others do better?

They positioned their small little robot on the start line. And off it went, like a snail. Their approach (after already disintegrating their first robot against a wall) was to take it slowly and precisely. After what seemed like an eternity their robot finally crossed the finish line and stopped perfectly on target.

We added up the times of all races and our team had just won. Wahey!

Retrospective

We looked back at what we had achieved. Although being told very little we had all learned a lot.

We had real experience of The Planning Game, making rough estimates and adjustments based on previous experiences. It was a lightweight process that kept us on track throughout both iterations.

We learned the lessons of Simple Design. Remember how much time we spent in the first iteration refactoring our robot to allow it to go around corners? Well we didn’t need that at the time and it turned out that that story got reprioritised to a story that we never even got close achieving. Think of all those higher priority tasks we could have implemented in that time. The other team were telling tales of how they spent most of the first iteration trying to be clever with cogs and pulleys when they didn’t need any of it -–they too wasted a lot of time. Overall we stuck to the principle of Simple Design for the rest of the project and we achieved a lot.

Pair Programming was essential. Without it knowledge transfer would never have happened so fast. Through pairing we really acted as a team rather than a collection of individuals. We worked off each other’s thought processes to make one person’s great idea even better. When we got stuck our partner would take over and keep the momentum going. As a team, we rocked.

By Refactoring, we prevented ourselves from over-engineering and tried to produce the simplest design where possible. After each chunk of work we needed to add new functionality but without refactoring we would have ended up with a spaghetti nightmare (both for software and hardware).

Rotating roles enforced Collective Code Ownership. This meant that we never ended up with the software person or the one who wrote that piece of code. Any change we wanted to make to any part of the system we just did. There were no bottlenecks in the team caused by ownership. At one point the hardware team realised the motors needed to be reversed. It was suggested to use a little trick with the wires as a workaround to reverse the polarity but because I’d just come from the software team I knew how easy it was to change it in the software.

We practised Continuous Integration by integrating the software and hardware at the end of each small task. This kept us focussed at all times in building a working robot and showed up problems in the working system early and often to allow us to adapt. A working robot with not many features is infinitely more useful than one with loads of features that doesn’t work at all. By the end we had our integration process so streamlined that we managed to fix a bug in the software, integrate it onto our robot and test it all within the final twenty seconds.

Our On-Site Customer was receiving and providing constant feedback on the project. The customer was happy that they could reprioritise features as their needs changed without being told they’d have to wait a long time. They enjoyed seeing a working robot very early on, mitigating the risk associated with big-bang style deliveries. We managed to gauge what made the customer happy and what upset them, adjusting our efforts accordingly. Whenever the delivery team had a question, we’d forget about playing the guessing game and ask the customer directly. The customer also drew our attention early on to things we weren’t aware of.

Because we had Small Releases, both the customer and delivery team managed to take into account lots of information in our second iteration that we learned from our first race.Going back to the original three objectives for this workshop, we delivered a product, learned a lot about XP (and Lego, and each other) and it was great fun.

As well as a good teaching exercise, this was an excellent team building events. Although we had not worked together previously we came out feeling like a powerful team.I recommend this workshop for anyone who wants to get a feel for working in an XP team.

Thanks to all the organisers, presenters and attendees.