Random stuff from a software developer

Impaired Programming: How neither of us is as dumb as both of us

Several months ago, the programming team I am on decided to try out pair programming. The title of this paper is not a judgment of how I feel about pair programming at all, but rather an observation on one of the potential pitfalls of it.

Overall, I’m inclined to think that there can be great benefit in using pair programming, but I think it is very important to execute properly and make a few very important decisions.

It should be noted that we’ve only been at this for a few months, so I don’t consider myself an expert on pair programming, nor did I do an exhaustive study of the subject. However, I do believe some of the observations I’ve made are valuable and will be helpful to anyone considering pair programming.

Also, in numerous occasions, I refer to a “stronger” and “weaker” programmer. This is not as absolute as it sounds, but rather is relative to the task at hand – a senior programmer may be the weaker member of a pair in one context, even if paired with an intern! Everyone has different experiences and skill sets, and it shouldn’t necessarily be a bad thing if you are the weaker member of a pair on a particular issue. In fact, if you are never the “weaker” member of a pair, you are probably not learning a whole lot and are not really benefiting from pair programming as much as others might.

What is Pair Programming?

Virtually all of us have practiced pair programming at one point or another – usually by calling over a colleague to help us tackle a difficult problem, explain an unknown piece of code to us, or help us implement something new. “Pair Programming” is simply making this arrangement official – by assigning a partner to have for a specific amount of time, specifying when and how they should pair, and assigning work to pairs instead of individuals.

Pair programming also implies two programmers and one keyboard. You might be inclined to think that this would lead to a halving of productivity. Proponents of pair programming argue that the benefits cause long-term productivity of pair programming to be greater than that of two individual programmers.

I do think it is certainly possible to see substantial gains in productivity as a result of pair programming, but it is also possible to see productivity suffer by more than half. It all comes down to implementation.

Benefits of Pair Programming

There are several supposed benefits of pair programming. Which ones your team finds most important will depend on your team, the technology you use, and the project you are working on. That said, generally I think you’ll see (or at least look for) the following benefits:

1. Two brains are better than one when approaching difficult or new tasks.
2. Working in complex and/or difficult to test parts of the application is easier if two people have eyes on it.
3. Fewer bugs.
4. Transfer of knowledge.

First, difficult or new tasks can be much easier with two programmers working on them. Having someone to bounce ideas off, or simply listen to your logic and think about it in a slightly different way is very valuable.

Second, many applications have their own scary part of the code – whether it is very complex, poorly written, mission-critical, difficult to test, or a combination of these. Having an extra set of eyes to spot potential pitfalls and navigate through the code is probably pretty helpful, and probably more than a little comforting to the programmer.

Third, having another person watching theoretically reduces the number of bugs in an application. This one is, in my mind, the most debatable, for reasons we’ll see later. From my experience, the bugs that are caught by the other person in a pair are almost exclusively minor problems that would be caught by even a mediocre unit test.

Lastly is the transfer of knowledge that occurs in a pair – which is probably the best argument for pair programming. Attempting to maximize the transfer of knowledge is also often the biggest productivity-killer in pair programming. Balancing productivity with the need to transfer knowledge is the main focus of this paper.

Balance

Most teams don’t have the luxury of spending months to provide training for everyone, and indeed, some of the best training occurs in the course of a project anyway. Pair programming offers a way to formalize and optimize this transfer of knowledge – you can team people up for optimal knowledge transfer, assign them tasks that will maximize new knowledge they have to attain, and have them work together in ways that requires one or both to learn the most.

The only problem is that most projects must meet their dates. Transferring knowledge usually comes at the expense of productivity – it takes me far longer to explain to someone why I did something and all the alternatives than it does to simply do it myself. Certainly some projects have more flexibility in their timelines than others, but I’ve yet to see a project that can be delayed long enough to allow for maximum knowledge transfer.

Transferring as much knowledge as possible without jeopardizing your dates requires delicate balancing. Should you choose to practice pair programming, there are several decisions that must be made – all of them should be made with this balance in mind.
Who gets paired with whom?

It might be tempting to match the strongest programmer with the weakest, in order to maximize knowledge transfer; or vice-versa, matching the two strongest programmers in order to maximize production. I think the pairings should be closer to random, except with a bit of looking ahead to see what tasks are to be accomplished. Eventually, everyone should have paired with everyone else at least once.

As a general rule, managers and leaders should be cognizant of the strengths and weaknesses of each team member, and pairings should be made with that information in mind. For example, if one developer is not as strong in writing good test code, he or she ought to be paired with a team member who is. I’ve seen some pretty amazing results in several cases doing this.
How long do people remain paired?

This depends on whether your focus is on productivity or knowledge transfer. I found that after our first iteration (3 weeks), we were working together far more efficiently. On the flip side, most of the knowledge transfer also occurred in that first iteration. Shorter pairings will probably maximize knowledge transfer, whereas longer pairings will maximize productivity.

How do pairs actually program?

We originally said that the person who could accomplish the task at hand the best would sit behind the other person who actually controlled the keyboard and performed the task. In some cases, this is still a good idea, but I found it to be less than optimal in other cases.

I found the best method was actually for me to do it the first time, explain what I did, and then hand the keyboard over to the other person and let them do it the next time (or vice-versa). How you implement this may depend on your team, your deadlines, and the tasks at hand – but I don’t think having the weaker person at the helm at all times is a very good idea in most cases.

This process can be extremely difficult for some programmers. On several occasions, I found myself to be less of a pair programming partner and more of a backseat driver – my poor partner!

In fact, this is the very issue that gave rise to the title of this paper. At one point, he was implementing something relatively trivial, but I thought he was doing it wrong and proceeded to “correct” him. Halfway through my “correction”, he thought I was headed down the wrong path and got confused. After a few minutes of talking about the problem, we realized we were both right, and that I should have kept my mouth shut.

Other problems arose when my partner was not typing quickly enough or was trying to figure out what to do next without talking to me. It took a while to get over the impulse to grab the keyboard and do it myself.

Programmers should try to be more patient (I am the most guilty of being impatient of anyone I know), and should refrain from interrupting the other person’s train of thought/typing. If there appears to be a problem, wait until an appropriate time to stop and talk about it.
What percentage of the time does a pair spend together?

Our team elected to mandate 100% pair programming. This is one thing I think we could have done better. Even if you mandate 100% pair programming, you won’t get it – or you’ll have one person in the pair twiddling their thumbs while the other half of the pair is out sick, in a meeting, running late, or any other number of reasons for being away from their desk.

Even more, however, requiring pairs to work together 100% of the time is a bad idea. There are many programming tasks we face that are relatively trivial, and none of the aforementioned benefits apply to them. Why pair on those? You are sacrificing productivity for very minimal gains at best.

In fact, there is a tendency for one person in the pair to get bored while the other is taking on a trivial task. Other programmers may sneak over to their own computer to read email, chat with a friend, or do something else non-productive. Other developers I’ve discussed this with hate pairing on simple tasks, and feel that it is a waste of time.

Research on this subject [1] has shown that while two programmers working on a complex task accomplish it more correctly without a time penalty, two programmers working on a simple task take longer to accomplish it with no benefit in correctness.

In general, I think it would be best for a pair to sit down at the beginning of an iteration and decide what work to pair on and what work would be best done alone. Using this model, where you don’t have a set percentage of paired time, you maximize the benefits without sacrificing productivity unnecessarily.

What tasks do we assign to a pair?

It may be tempting to assign tasks based on the abilities of the strongest or weakest programmer in a pair. How do you decide? I think a better approach is to aim for the middle. If the tasks are too easy (geared for the weaker programmer), the weaker programmer probably won’t learn much and the stronger programmer will get bored. If the tasks are too tough (geared for the stronger programmer), you’ll put a lot of pressure on the stronger programmer to do all the work, and the weaker programmer will learn less.

This means that if there is a particularly tough task ahead that can’t be split up, stronger programmers should be paired in order to complete it. It also means that tasks should be assigned that are probably a stretch for the weaker programmer, but not so much that it can’t be done in the time allotted.
Who is responsible for tasks assigned to a pair?

I think someone should be responsible for all the tasks for the pair, even though both members of the pair are ultimately accountable for getting them done. It doesn’t matter who is responsible, although it would be good to mix it up each iteration. They will be responsible for tracking and reporting the status of the tasks, communicating any roadblocks, and interfacing with other elements of the project time (QA, for example).

How do we judge a pair programming effort?

In my mind, a successful pair programming implementation is one where a team gains long-term productivity through the transfer of knowledge, improves the quality of their code, and doesn’t sacrifice so much short-term productivity that it causes external problems for the project.

As you practice pair programming more and more, I think you should see less actual pairing – indicating that knowledge is indeed being transferred, and programmers who were weaker in certain areas feel more knowledgeable and confident now.