Pair Programming Best Practices

  11 mins read  

In my experience, not a lot of developers pair-program.  This is easy enough to understand when you think about it.  After all, programmers are not a particularly social, (or hygienic), breed.  There’s also a general tendency to be territorial about code that makes it hard to share workload sometimes.  These challenges make it difficult enough to even show up at an office for some developers, imagine how difficult it must be for them to have to work side-by-side with another human being on the exact same code.

With that said, I think it’s a shame that more pair-programming doesn’t take place in the typical programming shop.  I don’t necessarily advocate for it in every situation, but there are certainly some areas where I feel like it’s a great way to increase productivity, both in the short and long term.  In this post, I’m going to talk about some situations where pair-programming is ideal, and contrast those situations against a few in which it’s actually a terrible idea.

When To Pair Program

There are 3 situations where I feel like pair-programming will result in a higher level of productivity than otherwise:

  1. An experienced developer with a less-experienced developer, as a teaching tool for the language/tools/codebase in use.
  2. Two equally experienced developers where one of them is encountering new code for the first time, provided that the other half of the pair has a solid understanding of the material being worked on.
  3. Two equally experienced developers working on critical parts of the system, (i.e., the ones that handle money or critical BI data, etc.)

Scenario 1: A senior/mid-level developer with a junior developer

A healthy organization will have a mix of skill levels on their development team.  A team of junior or even mid-level developers may not have the chops to tackle every task presented to them, and while a team of all senior-level developers sounds great in theory, in practice you might find that personalities clash a little harder when two people, both very well aware of their own value, butt heads. In my opinion, your best mix combines one or two really top-notch guys with a few mid-level developers and maybe 1 or two junior programmers. Naturally your composition will vary depending on the size of your team and specific needs, but the general idea is to spread out your skill-level curve if you can.

If you follow that advice, you’ll find that you have enough brain-power to architect your complex systems and tackle your stickier problems, combined with a competent group of developers that are perfectly capable of getting things done. With that said, your junior, (and even occasionally your mid-level), programmers will benefit from the opportunity to work closely with your most senior developers, and pair-programming is an excellent way to facilitate this.  You can learn a lot by simply seeing the end results produced by a solid programmer, but you’re going to learn even more if you have an opportunity to walk through their thought process with them.  Imitation may be the highest form of flattery, but it’s also an excellent teaching tool.  By pairing with more experienced individuals, a programmer at one level will reach the next that much faster, and from the perspective of a development team and the company that hires them as a whole, that means better productivity and better code.

Scenario 2: An SME with a SMN

I’m using SME to mean “Subject Matter Expert” and SMN to mean “Subject Matter Novice” in this context.  Even if you have two developers of relatively equal skill, (even if they’re both senior), there will be plenty of times where one of them has been working feverishly in one area of the codebase that the other has never touched or even looked at.  In fact, in a lot of development shops this is an incredibly common scenario as each developer ‘silos’ their own work. Proponents of pair-programming as a general practice point to the fact that it prevents ‘code silos’ as a major benefit, and I generally agree with them.  I do feel that there are times when a little bit of siloing is a good thing, but I’ll get to that later.

In any case, when you have one person who is extremely well-versed in a particular area of your code, and another person needs or wants to become familiar, an excellent way to accomplish the goal is to have the two pair up. As is the case in all pairing situations, the lesser-skilled, (or in this case lesser-informed), member of the pair is the one doing all the mechanical work.  They do the typing, they decide on the low-level implementation.  The person with the most domain-knowledge guides the session, answering questions, providing advice, and making higher-level decisions about architecture and so on.  This technique is great in the senior/junior pair for obvious reasons, but it can be particularly effective with two seniors or two mid-level developers, because a matching level of tool knowledge means they’ll be able to jump right in to focusing on the problems that need solving rather than spending too much time on the ‘how’.

Scenario 3: System Critical Components

I’ve always summed this scenario up with the phrase, “Never solo on the billing system.”  That was an oft-repeated quote in one of the first Rails shops I ever worked in, and the motivation behind it was clear.  The billing system held all the financials for all of our customers.  It handled every monetary transaction in the system, and it was subject to audit by multiple sources at any given time.  In other words, this system could not fail. While not every program in the world has systems whereby failure could cost the company literally hundreds of thousands of dollars, every program has systems that are considered internally critical, and any changes to these areas must be done with the utmost caution.

In most shops, (even ones that do pairing), the primary technique for making sure system critical failures don’t happen is twofold:  First, code is reviewed by another competent member of the team, with the understanding that ‘two heads are better than one’, and the other developer might catch something the first didn’t while they were deep in hacker-land. Secondly, code is never deployed straight from development to production.  Instead, an intermediate environment is used to test changes and ensure no serious flaws are present.  Both of these techniques are great, (even vital), but pair-programming on such critical tasks adds yet another valuable layer.

For one thing, if two heads are better than one, then it stands to reason that having those two heads actually working together while the feature is being developed is even better.  Incidentally, there are studies that prove why it’s two heads, (and not say 3 or 4), that provides optimal results when programming.  And of course, just because a pair of programmers actually produces the code, that doesn’t mean a third programmer shouldn’t look the result over.  With that said, it’s been my experience that a lot of code reviews are ‘phoned in’, by the person that does them.  They only check the very basics and only seem to catch really glaring mistakes.  On the other side of the spectrum there are those that will comment on every single minor detail or improvement, but they seem to miss the huge, glaring, ugly bug staring them in the face.  The fallibility of human nature comes in to play when you’re dealing with code-review, and pairing offers an extra defense against that.

When Not To Pair Program

Just as there are times when it’s ideal to stick a couple programmers together and have them hacking away, there are times when it’s just simply not a good idea.  I’ve seen shops attempt to impose pair-programming as a cast-iron standard…everybody pair-programmed…on everything.  The truth is that in practice, this won’t work all the time, and like most good ideas, pair programming must be applied where it makes sense, and foregone when it doesn’t. Personally, I feel like the following scenarios are not ideal for pair programming:

  1. Prototyping
  2. Minor tweaks, fixes, design changes, etc.
  3. Mutually well-understood areas of code

Prototyping

When I say prototyping, I don’t mean a prototype for an entire, large system, which could be paired on, I suppose. Prototyping by my definition is the act of writing ‘working’ code that demonstrates an idea or concept, without taking care of all of the details, and without rigorous design or specification.  Prototypes are used to determine the viability of a single feature, to flesh out requirements and/or problem areas, and to help with estimating the time it will take to develop the ‘real’ version of something.  By definition they are created through a process of experimentation, trial and error. Because there are no rigorous requirements or specifications to follow, there’s really very little the ‘navigator’ half of the pair would have to do in the actual process of coding the prototype.  Granted, open discussion with one or many other programmers is vital to the process of creating a prototype, but letting one senior guy go off and see what they can hack together is often the more effective way to generate good prototypes.

Minor Changes

Coming mainly from the web development world, I tend to categorize any change that largely affects HTML and CSS to be ‘minor’, provided those changes are under about 20 distributed lines of code or so. Granted, that’s a pretty arbitrary definition, and there are other cases in both web development and other programming situations, where a change would be considered small.  In those cases, it’s generally a waste of time to pair-program because:

  • There’s very little learning opportunity for a junior developer
  • watching a senior make a one or two line change, so there goes
  • scenario 1. If even a junior developer wouldn’t benefit from the
  • pair, how could you expect an equally skilled one to do better?
  • “Minor” changes by definition should not be system-critical, so
  • it’s generally safe to allow a single person to do them.

Mutually Understood Code Areas

If you’ve got two developers with an equal understanding of a relatively non-critical part of your codebase, there’s typically not a lot of point to pairing them up.  What will invariably happen is that one or the other of the programmers will set to work on the problem while the other one let’s their attention wander and does nothing.  You essentially lose the ‘non-typing’ half of the pair, because the ‘working’ half doesn’t really need to additional guidance and would probably resent it if too much was given.  I think this situation really illustrates the ‘Golden Rule’ when it comes to when to pair or not actually:  Pair when there is a disparity between the two parties with regards to knowledge of a particular problem. The more equally two people view a problem, the less valuable a pairing session would be.

Obligatory TL;DR

Pairing is a great idea, provided it’s applied to the right situations, and foregone when it isn’t the right fit.  In general, I think the following three situations are ideal for pairing:

  • When a more experienced developer wants to teach a less
  • experienced one about a language, platform or other tools. When
  • an experienced developer is approaching a part of the codebase
  • they’ve never worked on, and someone familiar with that area is
  • available to pair. When the area of code to be worked on
  • is extremely system critical.

By contrast, I wouldn’t pair in these situations:

  • When developing prototypes for specific system features. For
  • minor tweaks, fixes and improvements When both members of the
  • pair are equally skilled and familiar with the area of the
  • codebase to be worked on.

Finally, as a general rule of thumb, pairing is usually a good idea when there is a disparity of knowledge between the two parties, and generally a bad idea when they are equally capable at a given task.

Comments, questions, suggestions…always welcome!