The Value of Co-Location in Agility

Posted by Rick DeNatale Tue, 30 Jun 2009 11:48:00 GMT

Last night there was a very interesting extra meeting of the local AgileRTP group. Johanna Rothman was in town and Jared Richardson arranged an extra meeting so that she could present some of the issues which arise in adopting agile methods, and how to deal with them. Johanna is very knowledgeable and gave an interesting and thought provoking thought.

One of the issues she talked about was "distributed" agility. This is a hot button as many companies are outsourcing some development to "offshore" locations. Johanna talked about the issues in following agile practices, and I'm vastly oversimplifying here, pointed at time zones as the major issue.

Someone in the audience, who works in a distributed team with members across the US, questioned her on this. As the discussion unfolded, other issues came up, such as dealing with a team in China which had one person fluent enough in English who acted as the "email-translator", as well as cultural differences affecting communication.

Language and cultural differences certainly can inhibit the free exchange of information which is the coin of the realm in Agile practices, but I had to observe that these are not really geographical or time zone issues. I've seen similar difficulties with co-located teams.

Distributed development using agile methods can indeed work, I've seen it. OTI was quite good at it. We did timeboxed projects with development spread across the globe. A given project might comprise team members in Ottawa, Zurich, Sydney, Raleigh, and Vancouver. Large projects might use a "team of teams" but smaller ones had individual members who were geographically dispersed. There was lots of communication by phone and email, and it worked quite well.

OTI had one "stand-up" meeting every year, usually in February in the balmy clime of Quebec, an annual Tech Conference where everyone in the company got together at a sort of internal "OOPSLA" to talk about what they were doing and to exchange interesting ideas, and just get to know each other better.

Now the main thing that made this work was that we shared a common culture when it came to development. Although not everyone at OTI was a native English speaker, all were fluent.

"Big Dave" had a tendency to hire good people wherever he found them. Often such a person would seed a new multi-person laboratory, but sometimes a "lab" would be a single person.

So distributed development can work, and work well, given the right people.

Some agility advocates stress the need for co-location, a notable exception is Kent Beck, the founder of eXtreme Programming, who now spends most of his time based a his farm in southern Oregon, and does remote pair-programming using VNC and Skype, with programmers around the world.

And Kent is currently auctioning off a two-hour pairing session this is a good opportunity to sample distributed agility at a high level.

I wish I could afford to bid, the current bid is at $200, which is cheap. I've learned a lot every time I interacted with Kent personally in the past. Someone is going to get a deal, whatever the winning bid turns out to be.


RSpec Meet MultiRuby

Posted by Rick DeNatale Wed, 24 Jun 2009 23:41:00 GMT

Yesterday, David released RSpec 1.2.7, which includes a patch I provided to allow the specification of where to find the 'ruby' program when creating a SpecTask, rather than relying Rakes RUBY variable.

Why did I submit this patch you ask, assuming you didn't read the title of this post?

So you can do this in a Rakefile :

multiruby_path = `which multiruby`.chomp
if multiruby_path.length > 0 && Spec::Rake::SpecTask.instance_methods.include?("ruby_cmd")
  namespace :spec do
      desc "Run all specs with multiruby and ActiveSupport"
      Spec::Rake::SpecTask.new(:multi) do |t|
        t.spec_opts = ['--options', "spec/spec.opts"]
        t.spec_files = FileList['spec/**/*_spec.rb']
        t.ruby_cmd = multiruby_path
       end
   end
end

This is derived from something I just added to RiCal but haven't yet released.

What it does is check that you have multiruby, which is part of the zentest gem, installed, and that your version of RSpec supports the new ruby_cmd option. If both conditions are met it makes a spec task which runs the specs using multiruby instead of ruby.

Now it's easy to run specs with the various ruby versions you want to support.


Father's Day

Posted by Rick DeNatale Sun, 21 Jun 2009 17:23:00 GMT

A few days ago Corey Haines published an interview with his father about his father's programming career. Corey's dad, Terry, seems to be just a bit older than me and we started our programming careers about the same time.

This being Father's day, I hope you'll indulge me if I blog a bit about my dad, Joe DeNatale, who died just about 7 years ago.

Dad Paper

Silly Sinatra Application

Posted by Rick DeNatale Mon, 15 Jun 2009 03:46:00 GMT
Strangersinthenight
require 'rubygems'
require 'sinatra' 

def be
  "do, be, do, be, do"
end 

get '/strangers' do
   be do 
       be do
       end
   end
end
The thought occurred to me during Glenn Vanderberg's presentation on Sinatra at RubyRX a few months back.

Geek MugShots

Posted by Rick DeNatale Sun, 07 Jun 2009 19:24:00 GMT
Today, Josh Susser tweeted about his new french press and the quality of the coffee it produced, along with a [photo of his favorite mug, which happens to sport a nice Xerox Smalltalk design. So I decided to share some of my favorite mugs.

My everyday mug

J9Mug

This mug goes into the dishwasher every night, and comes out every morning, it commemorates the J9 Java virtual machine from OTI. The logo is derived from the VisualAge logo.




Mr. Tolley

Posted by Rick DeNatale Fri, 05 Jun 2009 13:07:00 GMT
Natale Crest

A couple of weeks ago, the RailsEnvy podcast covered RiCal.

So I got the honor of joining the long list of Rubyists who have had the pronunciation of their names butchered by either Jason or Gregg. That's OK, I love both of you jokers.

On the podcast it's pronounced something like din a tal.

Yes, I've heard that one before, less commonly than dee natalie, and many other attempts.


Singleton Methods in Smalltalk and Ruby

Posted by Rick DeNatale Sat, 30 May 2009 21:29:00 GMT

Yesterday, Travis Griggs posted an interesting article on his blog about a couple of tricks he used to write a test which needed to ensure that a race condition actually happened during the test.

And Randal Schartz just discovered it too. These two posts point out some interesting similarities and differences between Ruby and Smalltalk.


Selling Shoes to the Shoemakers Children

Posted by Rick DeNatale Fri, 29 May 2009 01:18:00 GMT

kbtweet Yesterday I took a few hours and attended an intro to SolidWorks at TechShop Durham. Then today Kent tweeted about how JUnit Max has been faring, and it got me thinking about the state of the business in software for programmers.


Safely dividing a UTF-8 String in Ruby

Posted by Rick DeNatale Thu, 28 May 2009 16:17:00 GMT

The other day, someone brought up a UTF-8 related issue with RiCal.

RFC2445 specifies that each line of a icalendar datastream must be no more than 75 bytes, and longer lines need to be folded by breaking them into sections with the second and following sections put into lines with an initial space character to mark them as continuation lines. As was pointed out to me, simply breaking a UTF-8 string in Ruby runs the risk of splitting up a multi-byte character.

Here's a spec to show what I needed:

describe "String#safe_utf8_split" do
  context "For an all-ascii string" do
    before(:each) do
      @it = "abcdef"
    end

    it "should properly split an ascii string when n leaves 1 character" do
      @it.utf8_safe_split(5).should == ["abcde", "f"]
    end

    it "should return a nil remainder if the string has less than n characters" do
      @it.utf8_safe_split(7).should == ["abcdef", nil]
    end

    it "should return a nil remainder if the string has exactly n characters" do
      @it.utf8_safe_split(6).should == ["abcdef", nil]
    end
  end

  context "For a string containing a 2-byte UTF-8 character" do
    before(:each) do
      @it = "Café"
    end


    it "should split properly just before the 2-byte character" do
      @it.utf8_safe_split(3).should == ["Caf", "é"]
    end

    it "should split before when n is at the start of the 2-byte character" do
      @it.utf8_safe_split(4).should == ["Caf", "é"]
    end

    it "should split after when n is at the second byte of a 2-byte character" do
      @it.utf8_safe_split(5).should == ["Café", nil]
    end
  end

  context "For a string containing a 3-byte UTF-8 character" do
    before(:each) do
      @it = "Prix €200"
    end


    it "should split properly just before the 3-byte character" do
      @it.utf8_safe_split(5).should == ["Prix ", "€200"]
    end

    it "should split before when n is at the start of the 3-byte character" do
      @it.utf8_safe_split(6).should == ["Prix ", "€200"]
    end

    it "should split before when n is at the second byte of a 3-byte character" do
      @it.utf8_safe_split(7).should == ["Prix ", "€200"]
    end

    it "should split after when n is at the third byte of a 3-byte character" do
      @it.utf8_safe_split(8).should == ["Prix €", "200"]
    end
  end

end

So to fix this I came up with a pretty simple idea, split the string and check to see if the second part is valid UTF-8:

class String
  def valid_utf8?
    unpack("U") rescue nil
  end

  def utf8_safe_split(n)
    if length <= n
      [self, nil]
    else
      before = self[0, n]
      after = self[n..-1]
      until after.valid_utf8?
        n = n - 1
        before = self[0, n]
        after = self[n..-1]
      end      
      [before, after.empty? ? nil : after]
    end
  end  
end

In RiCal, I actually implemented this using functional methods in another object, since I didn't want to 'pollute' Strings instance methods, but the code here illustrates the basic idea.


Ri_Cal is Now On RubyForge

Posted by Rick DeNatale Tue, 26 May 2009 21:34:00 GMT

After a few weeks of maturation on github, setting up a bug tracker, and a google group for project discussions, the bug reports died down to the point where I felt comfortable putting a more "official" release out on rubyforge.

Thanks to my most active 'beta-testers', Adam Williams who really drove the calendar generation DSL, and Paul Scott-Murphy, and Bruno Duyé gave a much needed workout to occurrence enumeration.

With folks from Australia and France providing input, it felt a bit like the old OTI days