Cory Foy

Thursday, October 09, 2008

Growing up Geek

image I've been tagged by Brian Button to tell a bit about my geek childhood. As you can imagine, I also had quite the geek childhood growing up. The picture to the left is my school picture where I'm actually posing with a Transformer.

Pretty much every aspect of my childhood was geekish in some way or another. From early childhood I was exposed to tons of electronics - we had a 200' tower in our front yard, my Christmas present one year was a homemade digital clock my step-dad made (which threw on whatever was plugged into the front of the clock when the alarm went off), and many other things.

image

Oh, and the satellite dishes. This was the "small" one in the backyard - 16'. We had a 20' in the front yard, a 40' across the street, and a pair of 10' in another part of the backyard. I clearly remember watching jets from Macdill Air Force Base to Patrick Air Force Base make course corrections once they saw the dishes. We got to do a ton of fun things - we used to pick up signals from Russian satellites, including newscasts of two very scared-looking people with a single bare bulb above their heads.

image

To make it more geeky, my mom and my stepdad actually got married in a helicopter. Yes, he was a pilot who built his own helicopters. So one of his friends flew over a chopper, my mom and him loaded up, and the rest of us listened over walkie talkie as the minister did the ceremony from the ground while the helicopter flew overhead.

image A lot of my geekiness comes from the fact that we also played a lot of Pool (or billiards) growing up. A good friend of ours won the national 8-ball championship, and it was a lot of fun learning about various aspects of math necessary to be a good pool player. The shot to the right was a suit that I had. Somewhere I had a picture of me in that suit on our pool table.

Even as I got older, pool was an important part of my life - although I just don't play it as much now. Perhaps that's something I should get back into.

As times went on, I got more and more into computers. My first computer was an Atari 800XL. My second computer was an Epson 386. I used to spend hours typing in programs from various computer magazines. I remember I even had Tetris, and it had a "boss" mode which would switch to a spreadsheet. Not that I knew what a spreadsheet was back then, but I remember thinking how clever that was. I was also into gaming - I participated in the Nintendo world championships, though I didn't get all that far. Somewhere we have a video of me, my mom, and a friend of mine dancing around a stage to Super Mario music. Hope that stays hidden.

image So, thanks to Brian for tagging me - it was great fun going through the picture box to find pictures like this one of me in my "Sun n Fun Fly-In" shirt. It's amazing how similar many of our backgrounds are across the blogosphere (we also did a bunch of Ham Radio stuff, though I never got my license). And it's a lot of fund seeing the different experiences we had which made us who we are today.

To keep it alive, I know hereby tag Brady Gaster, James Carr, and Gojko Adzic.

Sunday, October 05, 2008

New (or old) Mocking Syntax?

Is it possible to do the following, or do I have to use a Mocking framework? And if I do use a mocking framework, do I have to do anything special?


private IClassificationService fakeClassificationService = delegate {
System.Net.ICredentials Credentials
{
get { return null; }
set {}
}

IList ListAllProjects()
{
return null;
}
}


Edit: Looks like the new Rhino Mocks comes close to what I'm looking for

Friday, October 03, 2008

Build Status Lamp with Ruby and TeamCity

Recently at work we got our new build status light setup. We're using TeamCity as our Continuous Integration Server, MSBuild as the build script, and a homemade Ruby Script to control the lamp.

The setup sits in our team room and looks like this:

DSC_1028

The Build Lamp (a red lava lamp in this case) is controlled by an X10 Transceiver:

 

DSC_1030

I have a little X10 transmitter attached to the serial port of the computer you see. It's basically the setup from the Firecracker kit on X10.com. To check the status, we enabled the status widget feature of TeamCity, and I wrote a simple Ruby script to parse the widget using Why's awesome Hpricot parser and the CM17A X10 Ruby code from Rubyforge. That script is available for download but is just:

require 'hpricot'
require 'open-uri'
require 'x10/cm17a'

def there_are_failing_builds()
retry_count = 0
begin
doc = Hpricot(open("http://teamcity:8080/externalStatus.html"))
failingBuildElements = doc.search("//img[@title='Build configuration is failing']")
return (failingBuildElements.length > 0)
rescue
if retry_count < 3
retry_count += 1
puts "Network not available. Sleeping for 10 seconds then retrying"
sleep 10 #Wait for a bit to see if the network will come up
retry
else
puts "Could not open web page (Network is down?)"
return false
end
end
end

def turn_on_lamp()
puts "BUILD BROKEN! Turning On Lamp"
#Do it twice because sometimes the first doesn't take
X10.device('C1').on
X10.device('C1').on
end

def turn_off_lamp()
#Do it twice because sometimes the first doesn't take
puts "Build A-Ok! Turning off lamp"
X10.device('C1').off
X10.device('C1').off
end

puts "Welcome to the Build Monitor"

while(true)
if(there_are_failing_builds())
turn_on_lamp()
else
turn_off_lamp()
end
puts "Next status check in 60 seconds..."
sleep 60
end


We'll also play a build break sound (the team has chose the Macarena for now), but sound isn't working on that machine yet.



Happy hacking!

Tuesday, September 30, 2008

The Importance of Velocity for Product Planning

Recently there has been a lot of talk in the Agile community about moving away from estimated stories into more of a Kanban-style "pull-based" system. At Agile 2008, Joshua Kerievsky did a talk on MicroReleases where he discussed how his team did just that. They base the next release (which is just a couple of days away) on a gut feel of what the can accomplish. However, when you are working with teams who have a much longer release cycle, velocity estimates can be vital to product planning for both the developers and the business.

For example, when I worked at CARFAX we had to coordinate our releases with marketing efforts, campaigns, TV ads, etc. This meant that we needed to have a projection system we could utilize to estimate when we'd be done. So the business (in our case, the Product Manager) would bring the user stories needed for that release. We as a team would estimate them based on level of difficulty - 1, 2, 4, 8, 16, etc. We would then add up all of the effort estimates and add two cards - a budget card and a change card, both equal to 10% of the effort.

We worked in weekly iterations, so the first week we would commit to completing (code complete, QA, and Business Verified) a certain set of stories. In subsequent weeks, we could "sign up" for as many story points as we completed in the last iteration (also known as "Yesterday's Weather")

What this allowed us to do was project the end date (the part we could control of scope/quality/date) with great accuracy. On 6-month projects, we typically could release the week we said we would.

On the team I'm currently working with, we are dealing with a fixed date, since our release is tied around an entire user conference. What this typically meant in the past was that the development team was handed a list of specs, they did their best to try to meet that, and the last 3 months of a 12-18 month release cycle were the typical "death march" of 14 hour days, weekends, etc.

One of the first things I did when I came on board was to bring all of the stories and features that were spread across SharePoint sites, Excel spreadsheets, emails and people's heads into a centralized place, and have that place be the area where if the developers were working on something not in that system, they were in the wrong.

All of the items were estimated (or re-estimated in some cases) using the relative effort estimates. Our first iteration consisted of a gut feel of what they could complete. It seemed to go very well for them. The second iteration didn't - mainly because the first iteration was technical tasks, and in the second iteration, the agreement of teams not getting velocity until the story was coded, QA'd and verified by the business came much more into play. One team went from a velocity of 27 in the first iteration to 1 (yes, one) in the second iteration.

However, once we worked through those issues, we turned our focus to the backlogs and burndown charts. Based on each team's velocity, we projected out where we would be at the cut-off date for the product. What we found was that, at the date we wanted to be able to be code complete, each team would have 75% of their tasks remaining. As you can imagine, this was quite a shock to the management, who had been prepped for something like this to happen.

However, what happened next is one of the most important things a team can do, and perhaps the make or break point for almost any team. Knowing we couldn't adjust cost or the date, we began to work together as a management team to reprioritize the features based on the velocity estimates. Our executives could have simply rejected the velocities and creeded 14-hour days. Or ignored the results. But, instead, they took the information they were given early in the process and can now craft a response to it in a calm fashion without having to back out of promises.

In other words, in a previous release, this information would have been discovered practically at the end of the cycle - long after the release plans had been sent to the customers of what would be in the release, and after the agendas had been made for the conference. Literally the only option the team had was to nearly kill themselves to finish everything. Now, we can have serious, but calm, discussions about our strategy for truly delivering the most important business value in the time allotted.

We were able to make these decisions because we had solid information at our hand of what the teams were capable of, and what kind of effort we had laid out before us. Of course, nothing is perfect, and I'm sure velocity may change somewhat, stories may get added, or bugs may be found. But having the ability to report to the decision-makers what they can expect, couple with their willingness to work closely with the teams to deliver business value, can dramatically change how you build software.

Sunday, September 28, 2008

Making Tradeoffs

Last week, we had a small incident arise with the team I'm working with. Our Continuous Integration server is now live, meaning that code gets compiled with every check-in. This is great from the perspective of rapid feedback - if there is a failure, we don't have to wait for a nightly build - or for someone to have a problem on their machine - before we discover it.

However, this practice can be a bit overwhelming, especially in teams that haven't conquered the Five Dysfunctions. In this case, some of the staff were a little nervous that every change would cause a build, and were adamant that they had a specific need to check in broken code.

In cases like this, especially as an external change agent, it is important to step back and look at what is going on, and what solutions are. In this case, I have the authority to say, "This is how it is" - but it is very challenging to win the trust of the team that way.

Instead, recognize what is going on:


  1. Something new has happened, and so there may be pushback because it is change

  2. The feeling may be that the breaks would be used as a metric-stick to beat the developers with. In reality it is a tool solely for them, but not everyone has the trust of that yet

  3. Some people may feel very uncomfortable being put in the spotlight

  4. The CI server automatically forces 2 of the 5 dysfunctions - inattention to results and avoidance of accountability. Well, assuming the team doesn't just ignore the build server breaks

  5. There may truly be a need for someone to work in that manner. It may sound silly, but don't rule this out



Given that we want to keep our mainline building, and that not running the CI server isn't an option (nor having it not build on every checkin) what are the options we have?


  1. Work with the developers to understand their need, and offer help to mend the process so checking in broken code isn't required

  2. Have them move forward with checking in with the understanding that you'll work closely with them to fix any breaks

  3. Have them create a branch they can check in to, and then merge the changes back to the mainline once everything is in



So, even though it is tempting to just say, "Do it!", we have options at our disposal. In this case, I recommended options 1-3 above. And once we had a chance to talk even more (because they felt more at ease) they were able to internalize more of the reasons for a CI server, and it turns out that they didn't need any of the above.

So, as you work with your teams, it is vital to take into account the stages your team and the individuals are at. Sometimes we have to make tradeoffs in our process to account for the people. And People over Process is why we're doing this at all.

Wednesday, September 24, 2008

Follow up: Binary Clock in Ruby in under 55 lines of code using Shoes

After some great comments in my last post and some judicious refactoring, I now present an entire binary clock in Ruby in less than 55 lines of code using Shoes:


Shoes.app {
@width = 40
@left = 10
@margin = 10
@top = 180
@offset = @width + @margin
@fill = red
@images = [[],[0],[1],[0,1],[2],[0,2],[1,2],[0,1,2],[3],[0,3]]

def gen_recs(num)
  return stack {
    fill @fill
    num.times do |i|
      rect :left => @left, :top => (@top - (i*@offset)), :width => @width
    end
    @left += @offset
  }
end

def turn_on_images(num, stack1, stack2)
  time = num.to_s.split(//)
  t1 = []
  t1 = @images[time[0].to_i] if time.length > 1
  t2 = @images[time[time.length-1].to_i]
  activate_images(stack1, t1)
  activate_images(stack2, t2)
end

def activate_images(stack, image_pos_array)
  stack.contents.each do |item|
    item.style :fill => @fill
  end
  image_pos_array.each do |pos|
    stack.contents[pos].style :fill => green
  end
end

@hours1 = gen_recs(2)
@hours2 = gen_recs(4)

@minutes1 = gen_recs(3)
@minutes2 = gen_recs(4)

@seconds1 = gen_recs(3)
@seconds2 = gen_recs(4)

every(1) do
  now = Time.new

  turn_on_images(now.sec, @seconds1, @seconds2)
  turn_on_images(now.min, @minutes1, @minutes2)
  turn_on_images(now.hour, @hours1, @hours2)
  end
}

Sunday, September 21, 2008

A binary clock in Ruby using Shoes

When Shoes - a "tiny graphics toolkit for Ruby" - first came out a month or two ago, I was excited, but didn't really have much to do with it. Then it hit me - I love my Binary Clock on my iGoogle home page - why not build one?



The first thing to learn about Shoes is that you can stack things and then save them basically as an array. Since a binary clock has 6 columns, I created a variable for each column which contained the squares. This looked like:


@hours2 = stack {
  fill @fill
  4.times do |i|
    rect :left => @left, :top => (@top - (i*@offset)), :width => @width
  end
}


Which says to create a stack with the fill color of our fill, and draw four rectangles, bottom up.

Next, I had to figure out which images to turn on. The code to flip the seconds looked like:


sec = now.sec.to_s.split(//)
sec1 = []
sec1 = get_image_pos_to_turn_on(sec[0]) if sec.length > 1
sec2 = get_image_pos_to_turn_on(sec[sec.length-1])
turn_on_images(@seconds1, sec1)
turn_on_images(@seconds2, sec2)


Which isn't all that pretty, but works. For example, the get_image_pos_to_turn_on method is just this:


def get_image_pos_to_turn_on(num)
  images = []
  images = [0] if num == "1"
  images = [1] if num == "2"
  images = [0,1] if num == "3"
  images = [2] if num == "4"
  images = [0,2] if num == "5"
  images = [1,2] if num == "6"
  images = [0,1,2] if num == "7"
  images = [3] if num == "8"
  images = [0,3] if num == "9"
  return images
end


And, well, that's it. Which is the beauty of the Shoes app. It makes simple things simple. Here's a screen shot of it in action:



You can download the full source code from here: binary_clock.rb. You'll also need to download Shoes from the above link, and run the app by doing shoes binary_clock.rb.

And, this being my first Shoes app, I'm more than happy to take comments and suggestions for better ways to do it. Considering I did this whole thing in about 30 minutes with having barely looked at Shoes before, I'm pretty happy.