This post is another one brought to you by the good people at InRhythm. If you're an engineer that likes writing and building strong, happy culture focused on learning and growth you should apply! I like working with smart, passionate people :).
Lots of companies embrace pair programming as a way to increase programmer productivity (loosely defined here as delivering "value" which can have many forms) but is it really that great? I wonder why we should pair program and when is the right time to embrace pairing as a strategy. Pair programming, as I know it, came into popular culture as a facet of XP(extreme programming), a development framework that enforces certain practices that it considers to improve software quality and responsiveness. The idea is a new incarnation of the old adage "two minds are better than one". Possibly originating from the christian bible:
Two are better than one; because they have a good reward for their labour.
The quote is actually about friendship but if we take it out of context it can mean whatever we want it to. Anyway, the idea is right; Two people have different histories, cultures, and experiences and for those reasons they can think about things in different ways. When two people work on a problem together they almost always come out with a better solution that if one of them worked on it alone. So how does this relate to programming specifically?
The Good
Pair programming does reduce bugs
The primary drive for pair programming is to increase quality and decrease bugs and when done well, pair programming does that spectacularly. One study found that pairing reduced bugs in production by 15%!
Pairing does increase code quality
A lot of the benefits of pair programming are not actually technical, they're social. Pair programming is in some ways like having a boss breathing down your neck but one that you're comfortable who doesn't make you nervous at all. When you're working directly with a peer, you feel encouraged to do your best. Not only that, but you feel compelled to do your coding the right way and not let through those little bits of technical debt that you tell yourself you'll "fix later". These little bits of technical debt that usually slip through are a primary source of unmaintainable code. When you forget about technical debt, it's no longer debt; It's just bad code. When pairing we tend to do things just a little bit cleaner. We make algorithms just a little bit easier to read. We name variables just a little bit more sensibly. We actually write our unit tests to 100% coverage... With two people looking at the code, the quality is almost always higher than it would be with just one of them.
The Gotchas
Pair programming does not eliminate bugs.
Inasmuch as we'd like to pretend that pairing will just eliminate all bugs, that's not true. Bugs still happen. There are generally fewer of them but unless you have perfect programmers you're not going to have perfect code.
Pair programming doesn't fix bad product direction.
This is my number one pet peev right now. Good projects need very strong product direction. And to be clear, the responsibility for this direction is on everyone, not just "product people". It all has to start with people asking questions and making informed decisions about what work is going to be done. And then the team needs to thoroughly discuss the work in order to break it down as much as possible and understand the scope of work. If this isn't done properly then deadlines will be missed, everyone will be stressed, work that you thought would take minutes winds up taking days... Pair programming can't fix that. Nothing is more important than good product direction.
Pair programming costs a lot.
Like, a lot a lot. One study found that pairing increases the cost of software by 100%. While that seems like a pretty predictable number (if you put one more programmer onto a task you effectively double the cost), it's highly variable. If pairing is used effectively, I would say it strictly costs the amount of time put in, minus the value added. It could be a single-digit percentage. On the other hand, if pairing is done poorly, you're paying about 300% more. That's 100% for putting another salaried employee on the same project, 100% for that that employee not adding any value, and 100% for the work that they could have been doing if they weren't "pairing". So make sure that you're pair programming for the right reasons and doing it effectively or you could be paying up to 4 times the price for the same old software.
You have to do pair programming right for it to mean anything.
Pair programming is a tool meant to help make a difficult problem more digestible. It needs to be used correctly just like any tool. Pair programming done right generally involves one person writing code and the other person directing the work. Directing in this case means providing feedback about best practices and constructive criticism. It also means researching those best practices when you don't know them off the top of your head and taking the time to think deeply about possible edge cases and hangups relevant to the work at hand. Pairs should communicate constantly and make sure to share all relevant information about their work. And pairs should switch duties as often as they're comfortable. It's taxing to think about problems in both a creative and technical way so it's better to distribute that work. That's one big reason that pair programming is such an effective tool.
Pair programming doesn't make each individual programmer suddenly more senior.
When people work on a problem together, the intellectual benefits are additive, not exponential. This is an important distinction because we need to remember that adding another programmer to a problem can only make them about twice as effective. Adding a third programmer can only possibly make the group three times more effective and at that point you should already be seeing diminishing returns. When you have two junior programmers and you stick them on a problem together, they don't suddenly become mid-level programmers. They don't suddenly acquire more innate knowledge of systems and experience using tricky ways to improve systems. Two juniors will still make junior mistakes, just together. Two mid-levels will still make mid-level mistakes, just together.Even worse is if you have bad programmers. From a recent chat:
Me: It doesn't fix anything if you just have 2 bad programmers at 1 computer.
Coworker: And if a pair isn't collaborating, it's not pairing. Taking control is not pairing and neither is one person checking facebook while the other codes.
It's important to remember this when considering whether pairing is the correct tool to engage at the moment.
So when are we supposed to pair program?
Pair program when there is a very difficult problem at hand.
If you can't reasonably break a big problem down into smaller parts then you have a very difficult problem on your hands. That's the kind of thing that should be attacked with multiple programmers. An 8 point story should generally never exist in your organization if you're doing normal web work. Features can almost always be broken down into "front-end" and "back-end" stories. Whole-page mockups can be broken down into component parts. Design and QA phases can also be separated out into their own stories. But a really tough problem is just a really tough problem. Trying to add a new feature to a language is a really tough problem. Trying to figure out how to reduce the latency on database calls is a really tough problem. Those problems that you need to think about both creatively and technically tend to be really tough ones and you should use pairing to address those.
Pair program when 2 programmers are at completely different skill levels.
Pair programming is a remarkably good way to teach more junior programmers. Getting to watch live while a more senior programmer talks about how and why they're doing something is invaluable experience. So is writing code while a more senior programmer coerces better practices on the fly. The frequently of those "aha moments" is very high in a situation like this. In my time as a programmer, pairing with somebody significantly more senior than me has been some of the most difficult and most rewarding work I've ever done.
Pair program when 2 programmers have completely different skill sets.
If you choose not to break down a story into easily divisible parts, having 2 programmers with different but complementary skill sets can be very rewarding for both the programmers and the codebase. Examples might be pairing together programmers who generally only work front-end or back-end to get an end-to-end feature out the door. Or you might have a Postgres expert pairing with a Scala expert to make your database calls more efficient. When these 2 people work together live, they absorb a lot of knowledge about each other's domain and in turn make sure that there's no aspect of the project that gets neglected.
Pair program when you're both new to a language or framework.
Sometimes you wind up in a situation where nobody is an expert. Even if you're working on a trivial feature you've just wandered into a very difficult problem (see above). This is an excellent situation in which to pair program. There are extra benefits to this as well. Not only do you get two programmers working through a difficult problem and contributing their individual skills to building a better product and helping each other learn, you also get redundancy in the skill growth of your programmers. This is important because the skills in your organization should never be concentrated in one person. If that person gets sick, goes on vacation, or takes another job, you have a big organizational problem on your hands. Having programmers pair on new languages and/or frameworks ensures that there are a minimum of two people who can work on this in the future.
But don't pair program if you don't have a good reason for it.
Pair programming is just a tool. A fact that I will continue to emphasize. You need to have a reason to use a tool. If you're working in an auto shop and you don't know who your next customer is going to be, you don't immediately start out saying "I'm going to need a monkey wrench and exactly 4 bolts for the next job." That would be silly. In the same way, you shouldn't say that you're definitely going to pair on a programming problem before you even know what it is.
Don't pair program just because you're in a shop that considers pairing the norm.
Every decision should be made pragmatically. Pair programming is a tool just like code reviews or docker containers. You should only use it when it's appropriate. Like another quote that's popular in development shops:
Use the right tool for the job (possibly popularized by this ad campaign)
You have to make conscious decisions to use this and any tool for the right reasons. If you're wondering if it's a good idea, it's probably not. If your shop enforces pair programming all the time, talk to your leader and ask them why you do that and if they think it's always appropriate.
Don't pair program so that you can catch up on your messages while the other person drives.
This is the absolute worst reason to pair program. It costs the company 4 times as much to produce the exact same code (Because they're paying 2 salaries for 1 task and getting nothing done on another task). This is a way of creating useless process that prevents you from getting stuff done. If you as a programmer need to take some time to yourself, try taking regular breaks or walk around the block. Consider the pomodoro technique as a way to break up your day and keep your energy high.
Don't pair program if you both already know what you're doing.
This is very similar to the previous tip. If the task at hand is some sort of rote change or something similar to a task both programmer have tackled before then there's nothing to be gained. Pair programming is about learning and communication, not just a "life hack" to get stuff done.
Don't pair program just because it's an 8 point story.
Whether your point system is one that estimates time or estimates complexity, throwing 2 programmers doesn't reduce that estimate. If you're estimating time (which you should be), that story should take into account the number of programmers that will work on it. So if it starts at an 8, it's going to be like a 13 if 2 programmers are working on it. You're much better off putting your effort into making that story less complex and breaking it into smaller stories. Investing in your product direction like that is a much smarter and less costly way of improving quality.
Further reading
- Martin Fowler has a very inspiring article on pairing. I love puzzles and tricks so anything with "misconceptions" in the title is an instant win for me.
- On the nature of pair programming by Stuart Wray is significantly more optimistic about the benefits of pair programming than this article but he attacks it from a fantastically strong academic standpoint and standard and is very worth the time you'll spend reading it. Technical and sociological writing is rarely as well done as he does it.