I used to pair program now and then, but only for specific challenges. When I needed to implement a new feature in an unfamiliar area of the code, I might pair with the original author. I might collaborate on a particularly tricky algorithm or when we’re up against a tight deadline and it must absolutely be correct. And, of course, you put a team of engineers on it, when there’s that critical bug that happening to real people in production right now. A few months ago, I took a different approach. I started to pair program routinely. The experience changed my perspective entirely.

Background

I was working on a project where I wore two hats: product manager and engineer. In the engineering role, I had a small task to develop a Flash video client app and a Rails API that it would call. The other job was to write down requirements and work with the business owners to come up with a well-defined scope and project plan for the next iteration of the software. At the outset of the project, they gave me a demo. The site looked good and seemed to work well, it was just missing a few features and the application needed to be brought up to production readiness. After digging in a bit, I realized that the project needed more than one engineer to reach the desired launch date and ended up hiring Wolfram Arnold to work with me in building the Ruby on Rails web application and web services APIs. He asked me how I felt about pair programming and proposed that we pair about 2/3 of the time. Since I was relatively new to Rails and he was expert, plus he was new to the project and I knew the requirements inside and out, I felt this would strike a good balance. The business owners were unsure, but I argued that the easiest bug to fix is one that you don’t write. It was a relatively short 6 week contract, so we decided to give it a try. But first, we had to make sure that we had the right candidate for the job.

The Interview

I’m used to having a team of engineers at my disposal to vet a candidate, but in this case there was just me and a remote engineer to do a phone interview. I’ve always relied on seeing a candidate write code on the whiteboard to get a feel for how they think about code. However, I have always felt the whiteboard coding exercise to be a bit awkward, so we asked Wolf if he had any ideas about what we could do to affirm that he was the sharp engineer he seemed to be in conversation. Wolf suggested that we just pair on a real coding problem to complete the interview process. So we got together one afternoon and I picked a specific bug that I thought we could fix in about an hour. I was then introduced to a common pair programming setup that was nonetheless new to me: one computer, two keyboards, two mice. While unexpected at first, this was a very effective way to work. I found the switching to be naturally mediated by social convention. We discussed the problem, then dove in, taking turns, with me navigating to the right area of the code and us taking turns typing. We ended up spending a few hours together and fixed the bug (and wrote some tests and refactored code along the way), happily confirming that Wolf was as good as he seemed on paper and that we could easily work together.

Getting Started

The task at hand was a fairly tricky one. We were migrating a codebase from Rails 2.0.2, that relied heavily on the Globalize plugin for translation, to Rails 2.3 which includes built-in localization support. Additionally the plugin had been modified and the database had quite a bit of data which needed to be migrated forward. I immediately felt the speed of pair programming: I understood the database schema, product requirements and current feature set; Wolf could readily explain common Rails patterns (and the occasional anti-pattern) in the code and recommended good solutions. Together we were easily twice as fast as each of us individually. We found that there were a number of requirements that were unclear when we dug in and we spent about three weeks documenting these detailed requirements by writing tests for them. This was a critical step since we didn’t want to lose or break functionality when upgrading the code.  My favorite time savings in this phase was that we never had to call a meeting, whenever we would need to meet, there we were.

Escape Velocity

When we felt we understood the detailed requirements and has a core set of the features working well with tests to prove it, we dove into the upgrade preparation which involved removing the modified Globalize plugin, a few huge database migrations and some other important details. I had never coded anything so risky, so fast. If anyone were to code such a change solo, it would require careful focus and iteration ensuring that every detail were taken care of. You would naturally go slowly as your mind searches for each dependency and where you miss aspects and see test failures, you go back and fix your code and run again. As a pair of programmers, who were now familiar with the codebase, schema, and requirements, we flew. We each had our own checklists in our heads, as one of us typed, one kept a list on paper. When making any change, before we even ran the tests once, the one not coding would remember dependencies, notice typos or test cases not written that needed to be handled. The iterations were fewer. Each of us had time to think when the other typed. While waiting for tests to run, we discussed what else could go wrong or what we might do to double-check that it had all gone right. We were now coding at three or four times the pace that either would have going solo. And more importantly, we caught bugs in our brainstorming that would otherwise have been caught in a longer deploy-test-report-fix-deploy-verify cycle that is several order of magnitudes slower than when a developer notices an issue in the middle of a coding session.

Routine Speed

After we got through the most challenging and risky parts of the project, we continued to pair. Beyond my initial expectations that pairing would only accelerate the learning process, I found that even routine coding tasks and feature development were executed with breathtaking speed when we paired. While there were logistical reasons that we occasionally worked separately, the project moved forward most efficiently when we coded together. If anyone is starting a Ruby on Rails project, wants to adopt TDD or simply accelerate their development, I would recommend hiring Wolf. When we took the site live and moved on to work on separate projects, I found that I had grown used to the routine speed of pairing and missed the camaraderie as well. I wanted to achieve a similar acceleration on all of my projects, so I hired an intern, Lee Lundrigan, to pair with me. Lee didn’t have as much domain expertise, but he’s a very sharp engineer and does have some experience that complements mine. It’s not as fast as when I pair with Wolf — a dozen years or so of experience makes a difference. I’m guessing that it only doubles my speed.  I find the collaboration sharpens my attention and focus, in addition to bringing his perspective to the problem at hand.  The extra pair of eyes catch bugs before the first test run reducing debugging time.

Conclusion

If you haven’t tried pairing and you work in a team, just do it.  Give yourself a project for a couple of months to get a feel for it before you decide what you think.  If you work solo, consider hiring someone who is experienced with pairing and agile development to work with you to give it a try.  Take an opportunity when you are learning something new or have a big project you are taking on.  I’d be interested in hearing other people’s pairing experiences.

7 thoughts on “pair programming velocity

  1. Wow, Sarah! Thanks for the compliments. The pleasure was all mine. I’ve found pairing most fun and effective with another curious sharp mind on my side. I’ve been lucky in that regard, in several projects, including my first consulting experience with Scott Johnson at EduFire.com and now most recently with you for Mightyverse.com. What matters is the willingness to make a better product, to improve the quality of the code, the pragmatism of a business person and the sense of aesthetics of the artist. And one to keep me in check on all those aspects.

    In many ways I’m just passing on what I learned from others before, like the folks at Pivotal Labs that really showed me the ropes in pair programming, Agile development, leveraging Rails to the fullest. Some practical considerations that I find key are:

    Equal access to the machine by either pairing partner–that includes the physical seating position in front of the monitor and of course dual keyboards and mice–but also things like common tools so that either partner feels more or less at home. This might just be the time to look at IDE’s such as RubyMine and leave Emacs and vi for editing config files on remote servers. I also like the Mac/Linux environment we’ve had. Adapting to the Mac keyboard when coming from Linux is easy enough, but dealing with backslashes and other quirks of Windows might cut into your ROI more than switching to a Mac/Linux environment would be.

  2. Looks like fun, sarah! So you just hook up two sets of input devices, and the computer knows what to do? or you use blackbox switcher?

  3. Awesome post Sarah! At Hashrocket we pair 100% of the time! Our setup is 2 developers are hooked in via USB to a 30″ display. Makes it easy to see!

    I’m interested to hear what Wolf was using when he came in and if you had to adapt to learn a new tool as well? A slight speed bump when pairing is when developers have character maps (dvorak vs. qwerty) or might use different tools in their local user’s profile..

    Once Tim Pope (maker of Rails.vim) joined us, we started migrating towards Vi since he wanted to use Vi. Pairing has helped all of us become MUCH better at it. So there are some definite fringe benefits to pairing other than bouncing ideas off each other, cranking through features, or writing great code.

    Also, check out some of the stuff Corey Haines has been doing. He’s been traveling A LOT to pair with a lot of people and documenting the most of it!

  4. Before we started pairing, Wolf was using Aptana and I was using Vim. Wolf was not eager to sharpen his vi skills, and I was interested in learning about interative debugging techniques offered by an IDE. We had both heard of RubyMine which was in beta at the time and decided to try it out together. RubyMine worked well for us, and we learned the IDE together.

    We also worked on two operating systems with him on Linux and me on the Mac. This was awkward at times, but most of the tools (RubyMine and the command line) were identical. I did end up buying a spare Mac keyboard which helped since the keys are in different places.

    By the way, Wolf will be visiting Hashrocket the week after next and you can ask him about it yourself!

    Thanks for stopping by and continuing the conversation.

    Sarah

  5. Pingback: test-driven teaching | the evolving ultrasaurus

  6. OMG you lucky bastard J/K; I use rails.vim and have had to figure it out on my own and I’m probably not nearly utilizing it as I could. I ended up using more traditional command line to do some of the stuff that RGenerate, RServer, etc., do but would love to hear Tim Pope speak about using his awesome plugin. If you guys ever have something with him giving a presentation I would be “so there”. I also use NERDTree and some other choice plugins to do RoR. I’d also be curious to hear how has your Vim adoption come along at your shop?

What do you think?