On pair programming

Wed 24 May 2017

As I described at length in my Return Statement, I spent part of summer 2016 at the Recurse Center. In that piece, I mentioned pair programming as an important part of the RC experience. Being in an environment that encourages and facilitates it was a great opportunity. I paired for the first time at RC, but I felt that I didn’t pair as much as I could have. Anecdotally, it seems that many RC alumni also wish they had paired more during their batch. To help understand why pairing is worthwhile and why it can be difficult to do more of it, I decided to explore the topic in detail. In this piece, I’ll address two questions. First, what are the benefits and drawbacks of pair programming? And second, what are some concrete suggestions to make pairing sessions more successful?

In preparation, I read various blog posts and academic papers, tried a few pairing experiments myself, and talked with programmers I know about their pairing experiences. I’ll do my best here to summarize the conclusions I drew. First of all, I’d like to note that, in my opinion, there’s an important distinction between pairing full-time at work and pairing part-time and/or outside of work. Pairing full-time needs to be sustainable over periods of weeks or months, and different challenges arise when spending such a large amount of time working so closely with others. In addition, the goals of pairing sessions are different depending on the context. When pairing full-time, the main concern is having overall productivity and code-quality equal to or exceeding what is possible when working individually. With part-time pairing, the aim is to solve a specific problem or learn something new.

There isn’t a universal definition of pair programming, but it might be helpful to briefly identify what makes it different from ordinary collaboration. Perhaps this is obvious, but a key aspect of pairing is sharing one screen between two people. Talking with somebody about your code or sitting next to them and working on the same project separately doesn’t count as pairing. Most definitions of pairing mention an explicit division of labor between the “navigator” and the “driver”, with those roles usually trading off frequently. The driver is responsible for inputting text, while the navigator helps talk through problems, watches for mistakes, makes suggestions, and looks up reference material. This avoids the chaos of two people trying to type at the same time.

Technical aspects of pair programming

When looking at the benefits of pair programming, opinions seem fairly unanimous that it tends to increase code quality. One way it does this is by causing a dramatic decrease in the frequency of simple mistakes and small bugs. Avoiding small errors is hugely valuable, as anyone who has spent 8 hours debugging the results of a random typo can attest. Depending on your opinion about how costly these bugs are overall, this alone might be enough to justify pairing frequently or full-time. You could argue that linters and proper tooling can catch most mistakes of this category, but there are certain things that linters will miss. For example, if you have a typo that references a variable name that hasn’t been defined, a linter will identify the mistake, but if you accidentally refer to a different variable from the one you intended, the linter won’t give you an error.

From a bigger-picture point of view, you can also think of pairing as a type of constant ongoing code review. Having another person to discuss design questions with during the process of programming should certainly contribute to improving the quality of architectural decisions. However, one thing pairing doesn’t exactly provide for is time to think deeply. If you don’t explicitly make space for it, the fact that you’re talking and typing constantly while pairing doesn’t leave much time to think. If one person is convinced that they have the right solution, but the other has the feeling that there is more to consider, it can be difficult to say “wait, we need to take a break to think this over.” If there are differences between the pair in bias to action or active versus reflective learning styles1, one person’s ideas might be undervalued. If the best solution to a problem is not the most obvious one, pairing could make you more likely to miss it. I’ll talk more about how you can structure pairing to prevent these sorts of outcomes later.

Human factors

Many of the sources I read reported human-related factors as a major component of whether or not pairing is successful. The need for high levels of focus and constant attention mean that pair programming can be exhausting. If you’re more introverted, or if having somebody else look at your code causes anxiety, you’ll likely feel even more tired. If you’re pairing in the workplace full-time it will probably take a while to become fully acclimated and avoid ending every day with your energy levels depleted. One thing that helps is taking regularly scheduled breaks. I think pair programming integrates particularly well with the Pomodoro Method for this reason. In fact, this is a positive aspect of pairing: if properly organized and planned, it can help programmers maintain their energy levels and (hopefully) be more effective as a result. Having two people for accountability is more effective than relying on your own self-discipline.

One benefit of pairing that was mentioned repeatedly is that pairing is an actively fun experience. If you have a personality type that draws energy from collaborative activities, pairing is a way to satisfy that need with a pursuit that otherwise takes place in solitude. But, as I mentioned above, if you’re on the introverted side of the introvert-extrovert scale, pairing can be more stressful than pleasant. Even if you do find find working with others enjoyable, perhaps this is outweighed by the anxiety of exposing your thought process or self-perceived skill level to somebody else. For some people, programming alone is preferable, and this doesn’t make you less of a programmer or mean that something is wrong with you. In fact, it might even be useful to consider pairing a related but entirely different activity than programming alone. At least, from my personal experience, the subjective feeling of pair programming is different, much the same way that team activities or sports differ from things like running or painting on your own.

Another frequently mentioned benefit of pairing was the value of the constant exchange of information between pairing partners. In my opinion, one of the most fulfilling aspects of programming is learning from and teaching others. Additionally, sharing knowledge is a great way to clarify and solidify concepts in your mind. Multiple resources mentioned that knowledge transfer was particularly effective in cases with a gap in domain-specific knowledge. For example, an expert in a specific programming language can teach somebody else with a strong grasp of generalized programming concepts a large amount in a short period of time. A team with diverse backgrounds that encourages pairing probably distributes knowledge rapidly between its various members, which likely results in a high rate of individual growth as programmers. In today’s hiring market, where so many companies claim to be struggling to find more experienced programmers, pairing seems like a secret weapon to combine with the alternative strategy of hiring less experienced candidates and teaching them what they need to know.

Every programmer knows that programming can be extremely difficult and frustrating. This can inevitably lead to procrastination, regardless of how much discipline you have. Pairing is a great way to help cope with this problem, because it gives you a partner in helping to stay on task. Several of the blog posts I read reported that pairing decreased the amount of time they spent repeatedly checking email and doing other menial tasks. This is great for everybody: programmers are more productive, and they can spend less time working to achieve the same results. To me, 6 to 8 hours of highly focused work is much better than 10 hours littered with distractions and suboptimal use of time.

Suggestions for better pairing sessions

As I’ve discussed, there are both benefits and drawbacks that come with pair programming. Some of these are inherent; for example, if you have strong introvert tendencies pairing will probably be more difficult for you. However, there are specific ways to structure pairing that can result in higher levels of enjoyment and productivity. I’ve already mentioned one: taking frequent breaks to avoid burnout. Another solution to burnout is to rotate pairing partners frequently. After all, many of us have experienced that spending too much time with the same person can be exhausting. This is also a solution to not having enough time to think deeply while pairing. A 30 minute break to read reference material and think about the problem individually before regrouping can pay great dividends in that regard.

When pairing, try to have clear expectations and goals for each session. Of course, it’s fine to ask somebody to pair with you and figure it out as you go – spontaneity can be worth preserving. However, it’s definitely worth it to take a moment and say, “this is what we want to accomplish, this is how long we’re going to work before taking a break, and this is what we’ll do if we get stuck.” If one person thinks the goal of a pairing session is to fix a specific bug, and the other thinks that the goal is to learn more about a general topic, the session is less likely to be successful. The importance of communication lasts during the pairing session as well; if things aren’t working, it’s important to speak up and try to change something. One sometimes underrated aspect of good communication is generally just being kind and respectful. Facilitating an environment where everybody can speak up if they don’t understand something is also important2, especially when there are potentially large knowledge and experience asymmetries.

It’s easy for the more experienced programmer to dominate a pairing session, especially when the difference in experience is large. In that situation, it helps to let the less experienced person drive. It might result in things moving slower, but it will ensure that they aren’t being left behind. One surprisingly frustrating aspect of this arrangement can be that newer programmers are often slower at inputting text and using the keyboard efficiently. There isn’t an easy solution, but the more experienced person can take the opportunity to teach a few keyboard shortcuts. Another particularly tricky part of pairing occurs when each person has a different idea of how to solve a problem. At that moment, being willing to try the other person’s solution first regardless of who you think is right can really improve the experience for both of you.

Another important aspect of pairing successfully is making sure to use the right tools. If you have access to an external monitor, the extra screen space and visibility makes a big difference. I experimented with pairing using two keyboards and found it interesting and useful, although it did make it easier for the navigator to take over from the driver, so some level of structure and communication was required to avoid frequently “interrupting” each other. One surprisingly large barrier to effective pairing is differences in text editor preferences and configuration. It won’t be easy to switch between driver and navigator roles if you have to reopen the document in a different editor or switch to using a different shell each time. From a more philosophical point of view, this seems to me to be an argument against “excessive” customization or using niche tools. I might be wrong though – Vim and Sublime are both widely used, and yet fairly incompatible. I’m not sure there’s a great solution to this, other than perhaps making an effort to be familiar with multiple different text editors, or prioritizing pairing with people who use the same text editor as you.

Other thoughts

If you’re interested in pairing more but don’t have something like the Recurse Center to facilitate it, there are several possibilities. The first is to try pairing more at work! It might take some extra effort to better structure your environment for pairing (perhaps involving some of the above suggestions), but otherwise, you just need one other interested coworker to get started. If you don’t currently work as a programmer, you can pair with a friend or find a pairing partner at a meetup. Pairing doesn’t necessarily involve working on a massive project or something with real-world applications. Just pick a problem from a site like Project Euler or Hackerrank and see how far you can get in an hour. In fact, these smaller problems are a great way to start, because it’s a small commitment if things don’t go as well as you’d hoped.

There are some interesting questions to ask about pairing from the perspective of a team lead or manager. From a company’s point of view, the concerns about pair programming seem twofold. First, will the potential increase in code quality and employee happiness be worth the tradeoffs? As an extreme example, for a startup with 4 programmers, switching from 4 to 2 ongoing “lines of development” by pair programming full-time sounds pretty scary. It seems like it’s still probably worth it if your team will be more productive overall, but it’s certainly a valid question. Second, what will you do about the otherwise excellent developers, either current or prospective employees, who aren’t comfortable with pairing? Fortunately, I think that pairing doesn’t require a large initial commitment. You can start by making a small investment in arranging your space to make it easy to pull up a chair and join a coworker at their desk, and then see if you have any team members who’d like to take advantage of it.

Another exciting development is the elimination of physical proximity as a constraint for pairing. There are numerous tools emerging for pair programming remotely. The simplest option is to just use the screen sharing feature in Skype/Hangouts etc. This doesn’t allow for easy switching between navigator and driver, but for a casual pairing session, that might be fine. There are also more specialized tools, such as Screenhero, Floobits, or tmate, which allow both people to type in a shared text editor. I haven’t tried any of this category yet – maybe I’ll write a post in the future reviewing some of them, but I wanted to be sure to mention this as something worth exploring.

It can be difficult to get started pair programming, but it’s a great way to grow as a programmer and to write better code. I hope that reading this has inspired you to consider pairing more, and that there were some useful suggestions that might make pairing work better for you.

The sources I used:

Thanks to Laura Lindzey, Julia Evans, Khalid Omar Ali, and SengMing Tan for their advice and suggestions. Also to Rose Ames for doing a few pairing-related experiments with me.