Starting a Technical Book Club

Share:        

Book Club

I’ve started a couple of technical book clubs in my career. Both had some key ingredients for success:

  • A mental skill
  • People lacking proficiency with the skill
  • A desire to learn the skill
  • Safe to fail environment
  • Periodic time where the group could meet

Mental skills

For physical skills, I start by teaching a basic skill, followed by repetition with subtle variations designed to keep it interesting as well as expand awareness of the problem space. For example, when I was a taekwondo instructor, I’d teach a kick a certain way. Once students showed repeatable success with the kick, I’d focus on an aspect of the kick – kick higher, kick faster – until it exposed a new concept, at which time we’d focus on that.

By mental skills, I’m talking about the category of skills programmers use – cerebral pursuits where the skill consists of knowing strategies and techniques and applying them to situations. Mental skills include programming languages, design patterns, principles and practices. I find that the mental skills acquisition is similar.

I have less experience with social and spiritual skills, maybe you have an approach you’d like to share in the comments.

People lacking proficiency with the skill

An environment ripe for a book club includes an application of the skill in question. If I’m mentoring a group of developers that are all weak in design patterns, it’s an easy sell to read a book about the subject as a group.

A desire to learn the skill

Desire is a prerequisite for learning any skill. If a person doesn’t want to learn, they will avoid situations where learning can occur, like a book club. I’ve never been in a position where a book club was required, but I have been in teaching situations with people who don’t want to learn and find them to be very difficult.

Safe to fail environment

In my experience, people struggle to learn in situations where they feel pressure to perform, or at least to avoid embarrassment. Learning is hampered when attention is split between acquiring proficiency and auditing their own performance.

Periodic time where the group could meet

There are more effective ways of learning a mental skill than reading a book. For example, if I’m trying to learn a new programming skill, I will choose pair programming when it’s available. I should mention here that having the right partner is crucial to success. I look for people who are good teachers, patient and good at explaining things in multiple ways.

Pairing is highly interactive, and I get a chance to do two key things:

  • try to apply the new skill
  • have an experienced person model the correct behavior

This allows me to “act as if” I had the skill until I can do it on my own.

The natural extension of pair programming is a code kata, where multiple people get together to program. It can be hard to find the time – I’d recommend 1-2 hours each week. Scheduling can make a code kata impractical.

However, a book club can provide a muted version of this experience. The mentoring that happens with pair programming comes from a book, which has the advantage that you can read sections over and over. The downside is that the book only explains the new skill one given way.

The book club helps overcome this deficiency with group discussion, as well as providing a pool of people who are in the same learning situation as you are. The hope is that at least one person will get each concept and can help the others catch on.

Why not just read it alone?

To my mind, good learning environments include:

  • examples to learn from
  • freedom to make mistakes
  • an element of play

A good book club can provide all of these things better than an individual reading experience. When other people ask questions and offer opinions, more learning situations are provided than by a book alone. People bring their own experiences to a book, and this effect is magnified by multiple people.

The element of play comes from a social forum of like-minded individuals. In groups with a minimum level of trust, honest opinions can be shared. People can experiment with new ideas and concepts without fear of lasting consequences.

This is not to say there are no repercussions for making mistakes: with no cost of failure, there’s no reward for succeeding. Good learning environments include a penalty for failure that participants are willing to pay.

This is why games are such effective teaching tools: a simplified learning situation, consequences which are easy to tally and last only until the end of the game, and a structure made to promote fun. In short, games allow people to focus on one aspect of a problem.

Which book should I pick?

You want a book that hits the sweet spot for the group. In both book clubs I ran, successful books were:

  • relevant,
  • pitched at the appropriate skill level,
  • easy reading (small chapters), and
  • entertaining

Here are some books that succeeded:

  • Working Effectively with Legacy Code by Feathers
  • Clean Code by Martin
  • Head First Design Patterns by Freeman, Freeman, Bates and Sierra
  • Professional Test Driven Development with C# by Bender and McWherter

Here are some that flopped:

  • Domain Driven Design by Evans, too thick and dry
  • Working Effectively with Legacy Code, examples in wrong language
  • The Power of Less by Babauta, I was in the minority who liked it
  • Strength Finder 2.0, we didn’t share our results

As you can see, your mileage may vary.

Books I recommend that I’d enjoy reading as a group:

  • Growing Object-Oriented Software, Guided by Tests by Freeman and Pryce
  • Management 3.0 by Appelo
  • Managing Humans by Lopp
  • The Pragmatic Programmer by Hunt and Thomas

Please, share you experience in the comments. What books have you read? What formats worked best for you?


BetaFish Part 3 - Scaredy Cat

Share:        

This is article 3 in a series of posts in which I introduced the idea of building an F# robot for Robocode. The last installment showed an improved version of the robot that didn’t bump into walls, but did quake at the sight of an enemy.

The twitching behavior I described in the last post is a result of receiving a number of events each turn. When the robot is hit, it tries to evade. However, when it sights an opponent, it turns to attack. Evade, attack, evade, attack… the robot gets stuck in a loop as long as the opponent is facing it and continues to fire. Poor BetaFish. Let’s see if we can fix that:

  
 namespace Neontapir  
 open Robocode  
 open System

type ActionType =  
 | EndGame  
 | Search  
 | Evade of float  
 | Attack of float  
 | AvoidWall

type BetaFish() =  
 inherit Robot()

let random = Random(DateTime.Now.Millisecond)  
 let defaultFirepower = 3.0  
 let moveUnit = 20.0

let randomTurn amount (robot:Robot) =  
 let direction = random.Next 2  
 match direction with  
 | 1 -> robot.TurnLeft amount  
 | 0 -> robot.TurnRight amount  
 | _ -> failwith "Unexpected direction value"

let shouldEvade enemyBearing =  
 match enemyBearing with  
 | bearing when Math.Abs(bearing : float) < 20.0 -> false  
 | _ -> true

let evade (robot:Robot) =  
 robot |> randomTurn 90.0  
 robot.Ahead moveUnit

let mutable lastEvent : ActionType = Search

override robot.Run() =  
 try  
 while true do  
 match lastEvent with  
 | EndGame -> ()  
 | AvoidWall ->  
 robot.Back moveUnit  
 robot |> randomTurn 30.0  
 lastEvent <- Search  
 | Evade attackerBearing ->  
 match attackerBearing with  
 | bearing when not(shouldEvade bearing) ->  
 lastEvent <- Attack defaultFirepower  
 | _ ->  
 robot |> evade  
 lastEvent <- Search  
 | Attack firepower ->  
 robot.Fire firepower  
 | Search  
 | _ ->  
 robot.Ahead moveUnit  
 robot.TurnRight 40.0  
 with _ ->  
 lastEvent <- EndGame

override robot.OnScannedRobot(event) =  
 match lastEvent with  
 | Attack _ -> () // robot.Out.WriteLine "Scanned robot"  
 | _ ->  
 robot.TurnRight event.Bearing  
 lastEvent <- Attack defaultFirepower

override robot.OnBulletHit(event) =  
 let newEvent =  
 match lastEvent with  
 | Attack strength ->  
 Attack (Math.Min(strength + defaultFirepower, Rules.MAX_BULLET_POWER))  
 | _ -> Attack defaultFirepower  
 lastEvent <- newEvent

override robot.OnBulletMissed(event) =  
 lastEvent <- Search  
 override robot.OnHitByBullet(event) =  
 if (event.Bearing |> shouldEvade) then lastEvent <- Evade(event.Bearing)  
 override robot.OnHitWall(event) =  
 lastEvent <- AvoidWall  
 override robot.OnDeath(event) =  
 lastEvent <- EndGame  
 override robot.OnBattleEnded(event) =  
 lastEvent <- EndGame  

There are a few minor changes worth mentioning here:

  • I renamed the DoNothing ActionType to EndGamefor readability
  • I’ve encapsulated the defaultFirepower and moveUnitvalues for reuse
  • I’m doing more sophisticated pattern matching, like the nested match in Run’s lastEvent matching for the Evadetype.
  • I dropped the type specifications on the handlers for Robocode events, since F#’s type inference engine can infer them

To solve the twitching issue, I created a shouldEvade method that decides whether to try to evade fire. This version will stand and take it if it’s facing an enemy. I found it odd that I had to specify that bearing was a float type, until I realized that Math.Abs has a number of overloads.

I changed the signature of randomTurn so I could use the piplining operator (|>). This operator allowed to me write robot |> randomTurn 30.0, which reads more natually to me than randomTurn robot 30.0. With pipelining, I’m able to say “with robot, do a random turn”. My code less like Yoda sounds, pipeline it makes.

I wrapped the code in Run to solve another nagging issue. In previous versions, when the battle was over, BetaFish would often throw an exception or the battle simulator would have to terminate it. The try ... with _ -> lastEvent <- EndGame facility allowed me to catch the DeathException I often receive at the end of battle.

This BetaFish version, the one I’m submitting to the code kata, does far better than its predecessors. It almost beats the Fire sample robot. Fire often wins because it turns its gun and its body separately. If we get another go-round, I will try this strategy. I took a quick stab at it, but the first attempt did very poorly.

It still has problems, don’t get me wrong. It runs like a scaredy cat if it gets fired upon a lot. It’s performs poorly because it moves the whole tank body instead of just the gun or the radar. And it is easily defeated by the C# sample robot, that runs fast along the border and fires towards the middle. BetaFish can’t get a lock on it fast enough.

Beyond the robot, there are certainly more F# features to explore. For example, I’m halfway through reading “Real World Functional Programming” by Petricek and Skeet, and a future chapter teases at a better way to handle event registration and waiting on events to fire. I can’t wait!

I hope this article series has been of interest. Drop me a line if you found it interesting and would like to see more.


BetaFish Part 2 - Twitchy

Share:        

Last time, I introduced the idea of building an F# robot for Robocode. The second iteration contains some improvements:

 namespace Neontapir
 open Robocode
 open System

type ActionType =
 | DoNothing // end of game
 | Search
 | Evade of float
 | Attack of float
 | AvoidWall

type BetaFish() =
 inherit Robot()

let random = Random(DateTime.Now.Millisecond)
 let firepower = 1.0

let randomTurn (robot:Robot) amount =
 let direction = random.Next 2
 match direction with
 | 1 -&gt; robot.TurnLeft amount
 | 0 -&gt; robot.TurnRight amount
 | _ -&gt; failwith "Unexpected direction value"

let mutable lastEvent : ActionType = Search

override robot.Run() =
 while true do
 match lastEvent with
 | DoNothing -&gt; ()
 | AvoidWall -&gt;
 robot.Back 20.0
 randomTurn robot 30.0
 lastEvent &lt;- Search
 | Evade(bearing) -&gt;
 randomTurn robot (90.0 - bearing)
 lastEvent &lt;- Search
 | Attack firepower -&gt;
 robot.Fire firepower
 | Search | _ -&gt;
 robot.Ahead 20.0
 robot.TurnRight 40.0

override robot.OnBulletHit(event) =
 let newEvent = match lastEvent with
 | Attack strength -&gt; Attack (strength + 1.0)
 | _ -&gt; Attack 1.0
 lastEvent &lt;- newEvent

override robot.OnScannedRobot(event : ScannedRobotEvent) = lastEvent &lt;- Attack 1.0
 override robot.OnBulletMissed(event) = lastEvent &lt;- Search
 override robot.OnHitByBullet(event : HitByBulletEvent) = lastEvent &lt;- Evade(event.Bearing)
 override robot.OnHitWall(event) = lastEvent &lt;- AvoidWall
 override robot.OnDeath(event) = lastEvent &lt;- DoNothing
 override robot.OnWin(event) = lastEvent &lt;- DoNothing

You may recall me saying that the first version of this robot could be defeated by a wall. While trying to implement this feature, it became clear that firepower didn’t represent enough state for the BetaFish robot to care about. There were a number of intermediate versions between last post’s code and the above, as I experimented with created a class to encapsulate state.

While trying to use multiple classes, I was stymied for a time by Visual Studio. In an F# project, it wasn’t clear to me how to spread my solution over multiple source files. I couldn’t reference my other classes. I discovered that in a functional language, it’s necessary to order the source files to resolve dependencies, so that items do not depend on other items that are compiled afterward. It turned out that the classes I wanted to use came after the main class in alphabetical order. In Visual Studio, you can reorder source files in an F# project by right-clicking the source file in Source Explorer and moving it up or down.

After a number of iterations, I discarded that secondary class in favor of a discriminated union, which I called ActionType. Conceptually, a discriminated union is kind of like a generic C# enumeration, but of course much more useful. For example, notice that the Evade and Attack elements take a float argument, whereas the others don’t. And pattern matching provides a more robust way to examine the contents of an ActionType than C# enumeration’s ever would. To accomplish this in C#, you’d need a hierarchy of classes.**

**

The Run method has become more sophisticated also, now matching against the AttackType instead of just a scalar value. Notice that I’m able to name the union type’s argument inline, such as in the case of Evade’s bearing. This is a feature of pattern matching, not discriminated unions, as you can see with strength in the OnBulletHit event handler.

**

NOTE: While this code looks more impressive, it actually stinks in battle. If you try this robot, you’ll find that once BetaFish engages the enemy, the robot freezes in battle as soon as it’s hit, twitching until it is annihilated. Can you see why? The next article in the series contains the answer.


BetaFish Part 1 - a Robocode robot in F#

Share:        

The group here at work chose to compete via Robocode for our next code kata, and this post is the first in a series that describes how I wrote an F# robot for that challenge.

Robocode is a programming game in which a platform is provided, including an abstract Robot battle tank class, and competitors write concrete implementations. Those robots compete in real-time on-screen. The battle simulator has decent graphics, and the platform exposes a few dozen events that robots can subscribe to in their quest to be the last robot standing. For example, when the robot sees an opponent or hits a wall, an event is fired.

Robocode itself is written in Java, but there is a library called JNI (Java-.NET interface) that allows .NET robots to take part in the fun. Since I’m learning F#, it seemed like the language to choose.

First, I visited the site and downloaded the Java platform. I then followed the instructions for creating a .NET robot, which including installing JNI and some helper libraries. The instructions were written for C#, and being F#, there were some subtle nuances that I missed which cost me a couple of hours:

I followed the Visual Studio debug setup instructions included, but found that if I set a breakpoint prior to hitting F5, I got a fatal exception loading the JNI jar file. A colleague wasn’t having this problem, and we figured out he wasn’t setting breakpoints right away. Now, I use this workflow:

  • Disable my breakpoints
  • Hit F5 and let the Robocode battle simulator load
  • Enable my breakpoints
  • Start the battle

I found a post on Zamboch’s blog showing a very basic F# robot. It was enough to get me over the hump. Here’s the first version of the robot:

  
 namespace Neontapir  
 open Robocode  
 open System

type BetaFish() =  
 inherit Robot()

let random = Random(DateTime.Now.Millisecond)  
 let mutable firepower = 1.0 // TODO: handle this immutably instead?

let randomTurn (robot:Robot) amount =  
 let direction = random.Next 2  
 match direction with  
 | 1 -&gt; robot.TurnLeft amount  
 | 0 -&gt; robot.TurnRight amount  
 | _ -&gt; failwith "Unexpected direction value"

override robot.Run() =  
 while true do  
 robot.TurnRight 40.0  
 robot.Ahead 20.0

override robot.OnScannedRobot(event : ScannedRobotEvent) =  
 robot.Fire firepower  
 override robot.OnBulletHit(event) =  
 robot.Ahead 20.0  
 firepower &lt;- 1.0 + firepower

override robot.OnBulletMissed(event) =  
 robot.Back 20.0  
 firepower &lt;- 1.0  
 override robot.OnHitByBullet(event : HitByBulletEvent) =  
 randomTurn robot (90.0 - event.Bearing)  

You can see, it has a lot of similarity to Zamboch’s sample robot. The new piece for me was the randomTurn method. This was the first occasion I’d had to use the pattern matching (matchwith) construct.

Pattern matching is a little like regular expressions for code. Instead of writing a switch statement or a series of if/then blocks, I can use pattern matching to conditionally execute code. In the case above, I’m getting a random result between 0 and 1, and using that to decide whether to turn left or right. The F# compiler won’t allow me to specify an incomplete pattern, so I use the “match anything” (_) symbol to complete the pattern. The underscore is analogous to a default case in a switch statement.

You’ll notice that I have a mutable variable in this robot, firepower. Although F# supports mutables, I wanted to get rid of it. Typically, I’d do this by having a method that returns a new BetaFish robot. However, because the Robocode battle simulator expects a single instance of the Robot, this strategy won’t work. At my present knowledge level, I’ll need at least one mutable variable.
This robot isn’t very smart. In fact, it can be thwarted by running into a wall. In the next article, I’ll add some more basic functionality.


Case Study: Release Planning in Agile

Share:        

This is a story about how I applied my CSM experience and training to help a mid-sized project get off the ground.

Beginnings

When I came onto the project, the company was struggling with agile. They had been doing software engineering for a while, but in the context of controlling hardware. This project, an item state management system, was a departure for them. They already had a product in this space which they were essentially reselling from a consulting firm. The existing product was awkward to use, its feature set was limited, and the consulting firm did not wish to re-write the product to scale.

So, the company decided to write a replacement. They chose C# and .NET as the language. “Mason”, the principal engineer on the project, was a Java programmer by trade, so they needed some help. I was hired onto the team as a senior .NET engineer who could help mature Mason’s technical capabilities in .NET, and they had already hired a mid-level .NET engineer who started a few weeks before I did. It quickly became apparent that my CSM knowledge would be just as valuable.

The team had the desire but not the field experience. Mason had written a prototype, and after quick examination of the code, it was clear that his architecture would not support the ambition of the product.

The project manager, “Jason”, had chosen Scrum as the delivery methodology, yet he had no experience with it. He was on the right track with sprint-level work management, but he was having trouble with release-level planning. he asked me if I could help get the project back on track. The product owner, “Kathy”, already had a comprehensive set of use cases outlined. While they were not fully-baked, they contained enough meat to discuss in detail what the project is trying to accomplish.

Theme Sizing

I introduced the idea of themes. Kathy had already grouped the use cases into broad categories, so it seemed natural to think of these categories as themes. Jason and the product owner went off and grouped the use cases. They did it more fine-grained than I’d anticipated, putting them into a couple dozen smaller categories that I’d call epics.

I then introduced the idea of T-shirt sizing for themes. The goal of this was to talk about which parts of the application contained the greatest effort. Some use cases have some risk — we as a team aren’t sure how we’ll tackle them. Others don’t have enough definition. Still others represent a lot of work.

Over the course of a couple of afternoons, the team got them sized. The challenge remained, how do you use T-shirt sizes to create something that resembles the Gantt chart the project sponsors were comfortable with?

Theme Points

It hit me, these T-shirt sizes were a scale, just not a numeric scale. I needed to quantify T-shirt sizes.

Mike Cohn has an article about relating story points to hours in which he shows story points graphed as Bell curves. So I wrote a scale like this on the whiteboard:

Onesie  |  Small  |  Medium  |   Large  |     XL

I picked an arbitrary number to represent a Medium. I wanted it to be on a scale that couldn’t be mistaken for user story points, so I chose 500.

Onesie  |  Small  |  Medium  |   Large  |     XL
                      500    

Of course, a Medium is not exactly 500 points. These represent a broad range, so I declared that a Medium was 500±50%, or 250-750.

Onesie  |  Small  |  Medium  |   Large  |     XL
                  |   500    |
                 250        750

I extrapolated to determine the rest of the scale.

Onesie  |  Small  |  Medium  |   Large  |     XL
  60    |   180   |   500    |   1500   |    5000
       125       250        750        2500

This worked out to roughly powers of 3.

Onesie  |  Small  |  Medium  |   Large  |     XL
   1        x3         x8         x25        x83

Jason took these ranges and our commentary during sizing that Theme X seemed bigger than Y and assigned values to each theme.

So When Will That Be Ready Again?

By this time, we had already completed a sprint or two, enough that we had an idea that our velocity was going to be somewhere near 30. We had enough information to try to correlate these themes against a calendar. Projecting when we’d complete the epic’s functionality and armed with our velocity, Jason threw the numbers into a spreadsheet and started trying out numbers.

Our current epic was rated at 800 theme points. We thought we’d be done with it in 6-7 ideal days, which means 3 developers can get through about 750 theme points in an ideal week. This became 250 points/dev/week, a velocity of sorts.

Thanks to the spreadsheet, we were immediately able to see that calculated out to about 12 months to write the application.

Better yet, we were able to forecast what general area of the application we’d be working on months from now, which allowed us to project some milestones. We need to have this epic done by Halloween to be on track, that set of themes by Thanksgiving, and so on.

Of course, these numbers had a high margin of error. We communicated it would be more like 6-18 months to write it. We reasoned that as the team got a epic or two under our belts, Jason and I should have been able to refine the conversion rate and get a more realistic idea.

What If…

The real fruits of this exercise were that we now had a few variables that we could experiment with.

For example, that velocity of 30 was measured while we were storming as a team and 2/3 of us were new to the domain. Maybe we could expect the work would get easier as we learned the domain. This would be expressed as an increased velocity. If you increase the conversion rate from 250 to 300 after a month, you gain about a month over the life of the project.

A similar gain would be realized if a 4th developer is added after a couple of months. Other projections were made about the impact of adding a QA engineer early, which the project didn’t have until much later.

Course Correction

Of course, the project sponsors wanted it faster. To them, time to market was crucial. The company saw a dwindling market for their current offerings and were looking for ways to increase their reach. Their goals were compelling — it seemed like a good opportunity. This product would do things that others don’t.

Management needed a product that was feature-compatible with its competitors in the marketplace before the venture capital expired, so we were asked to come up with a plan that might possibly work.

We were able to use the spreadsheet to estimate how much of the application we’d have to de-scope to get it done in the timeframe we want, and Kathy was able to identify several themes as not mission critical to beta testing. The idea was that development would continue while the product was in beta, which I had discarded as too risky but Jason felt was viable.

Presentation

We presented the plan. It was, in the parlance of a senior company executive, a “success-oriented plan”. No one was comfortable with it, so some difficult conversations followed. The project was in a bad position.

There were two senior executives who vied for control of the project. One felt that the company should continue to sell their poor solution until the new one was ready. The other felt that the poor solution could not be maintained, should not be sold, and the new one needed to be rushed to market.

The second executive won and demanded a crushing work pace, complete with extended work hours. I knew from experience that such a pace was not sustainable and was prone to error on a product whose core had to be solid the first time. The customers in that market would not forgive a poor first showing.

I could not in good conscience proceed with the project as outlined, so I left. I don’t know exactly how the story ends. The other experienced .NET engineer on the team left for similar reasons. I have spoken to Mason, and he told me the project is very behind the schedule Jason and I laid out.

Conclusion

I think the exercise was worthwhile. Although the schedule Jason and I concocted was wildly speculative, it provided a frame of reference so that valuable conversations could take place. It got prompt and appropriate management attention to the project. The technique allowed us to do the analysis in a timeframe where its recommendations could be acted on.

Many of you reading this article have probably already formed opinions. It’s clear the project is in trouble. For me, it was that no project plan could overcome the fact that the delivery team did not have enough technical experience nor the business knowledge to rapidly develop such a complex product.

Without doing the analysis we did, I don’t think the errors in the original project plan would have surfaced until much later.