Firstly, as a massive caveat to this post, let me say that I’ve only ever worked for two companies. I have worked on different teams within these, but nonetheless I realise I don’t have a wide range of experience here. This post details some observations based on my personal experience of pair programming over the last four years.
So, pairing. Sometimes I love it. The two companies I’ve worked for are both huge proponents of pair programming. All of the teams I’ve worked on would say they pair program one hundred percent of the time (although in reality it ends up being less as you often end up with an odd number of people). I currently work for a consultancy that is probably the biggest advocate for pair programming I’ve ever come across. But personally, I must confess I don’t think it’s always the win.
I used to be totally sold on the idea. When you’re starting as a programmer out it’s great. You get to work with people who have more experience than you (everybody) and see how they work. You learn so much from doing this, not just about code, but about different ways of working and approaching problems. You also get to contribute real value from the start, which makes you feel like part of the team. This is all awesome. What you don’t get however, is to find out what you know yourself. How reliant on your pair are you? What would you do on your own? When you’re super new it can be difficult to take the keyboard as you feel like you’re slowing everything down and it’s hard not to end up discouraged when you’re trying to drive. You want to learn, but you don’t want to slow progress down too much, and you don’t want to frustrate the other person.
It can be difficult for the more experienced person too. Of course they want to help their pair learn. But they also want to be creative and explore different options, which can be really difficult with someone who doesn’t know what they’re doing. Perhaps this is most often the case where you have someone with very little experience pairing with someone with only a bit more experience. The individual with some experience may not know how to solve the problem and need to try out some ideas. This can confuse the less experienced person as it can mean jumping around a lot in the code. It also makes it difficult to offer direction to the less experienced pair if they are on the keyboard. You don’t want to lead someone else down a rabbit hole.
Pairing can work really well with two people of a similar ability. You can bounce ideas off of one another and share the work. You don’t have to explain every little thing so you can progress quickly. Of course this is too simplistic a scenario: it’s likely that one in the pair has more domain knowledge or understands the problem better. You are not necessarily both on the same wavelength even though you may have a similar level of technical skill. However it feels like the playing field is more level, which makes pairing more fluid.
Pair programming can be really hard work. This aspect is often overlooked. It’s intense, especially when you’re doing it for long periods of time. This is true even if you get on well and work well with someone (not always the same thing!). You’re in constant communication with someone else, which is tiring and requires a lot of concentration. If I’ve been pairing all day I’m exhausted by the end of it. I need to get away and de-stress by not talking to anyone for a bit. I’m not ready to have a conversation or answer questions about my day for a while; I need to recover from it first! You also have to share close physical proximity with your colleague . Even if they’ve got great personal hygiene, this can be a bit much. Little things become uncomfortable that you don’t usually have to consider. I have to excuse myself from my pair when I have a meeting and they don’t, when I go to make coffee, even when I need to take a toilet break. What if I need to leave early, or take an early lunch? These things all disrupt the flow of working.
Pairing can really suck if you don’t gel with the person you’re working with. There have been times when I’ve not looked forward to stand up because I don’t want to have to pair with person X. There are always people you work better with than others, just as there are people you get on better with generally than others. These things aren’t usually talked about though, which means re-pairing is driven by people trying to get what they want without letting on they’re doing it. I’ve been on teams that have stopped functioning due to bad pairing practices and people who fundamentally don’t get along and are made to work in very close quarters. Pairing can make problems about people and their egos rather than about technology. This is the crux of the issue for me. It’s why some days I love pair programming and sometimes I don’t.
Of course, just because something is hard doesn’t mean it’s not worthwhile. If pair programming is more productive, it’s probably worth overcoming the people problems. And most of the time I think it is more productive. I believe you work harder in a pair. You’re much less likely to start looking at kittens on the internet when you’re working with someone else. And if you do get distracted you’ll probably spend less time procrastinating as you’re aware that there’s another person who is also not working. Having someone to talk ideas through with all the time can be great. You’re much less likely to end up at a dead end if you’re talking everything through with someone else. Ideas have to be reasoned about, which means you have to think them through properly. There’s definitely a chance you lose some of the creativity you get from getting into the zone on your own, but you’re so much less likely to hit a wall. You also make less silly mistakes in a pair, which has to be a win!
So what are the alternatives to pairing? Another paradigm is where everyone works independently and we have code reviews. I have personally never worked like this, but I can’t see how it could work well. The person reviewing the code doesn’t have the same context. They can only reason about the style and (to a certain extent) the way you’ve done something, but not so much about if it is the right thing to do in the first place. Also it feels like a big chunk of time spent by the reviewer, who not only has to review the code and pick up that context, but also context switch from whatever they’re working on, and later try and get back into that. It doesn’t seem like a productive or effective way to work. Pull requests are another alternative but can still be a slow process. The requester may have to badger someone to review and merge their code. This puts me off doing minor refactoring and tidy up if I’m working on my own. Is my change really worth making a pull request for and then finding someone to merge it? Maybe that code smell wasn’t so bad after all. I do mainly agree with the theory that all code should have at least two pairs of eyes on it before it is committed to master. This makes sense especially if you’re deploying to production frequently. Pairing does seem like the most effective way to achieve the two pairs of eyes.
Maybe pairing just isn’t appropriate in every scenario. For example, my pair and I have started doing a big refactor to change the interface a bunch of classes implement (the sort of refactor where there isn’t a clever ide key combination that will do what you want and requires some manual work). You’ve found a nice pattern that fits and want to apply it to lots of different classes. You’ve had a look as a pair and it seems that it will be pretty straightforward. Does it require both of you to sit at the keyboard to complete this refactor? I used this in an interview (for my current job) as an example of why pairing isn’t always the win. My argument was met with the following counter: it sounds like I don’t want to pair on work that’s boring and routine. If I’ve reached this point have I lost track of why I’m doing the thing in the first place? Is it still the right thing to do? Is there a better way of doing it? In a pair someone is more likely to be asking these questions. A big advantage of driver / navigator style pairing is that while one person is typing, the other person is thinking about the bigger picture and asking these questions. Is it a smell that one person is sitting twiddling their thumbs and watching the other person type? Maybe, but I would argue that when it comes to refactoring, sometimes you have to go with an idea for a while, apply your new pattern and see how it works out. Obviously this depends (as always) on a host of things. How big is the change you’re making and does it really apply in all cases? Sometimes you don’t know these things until you’re done, or at least almost done. Only then can you take a step back and see the wood from the trees. I don’t think that doing this sort of refactor in a pair necessarily gives the non-driver this perspective: they are still too involved.
What if we broaden our definition of pair programming? Maybe it doesn’t always have to mean two people working at the same computer at the same time. It can also represent when two people are working on the same story, but have perhaps divided the work between them. The scenario outlined above is is a great candidate for splitting up like this. You can each work on different classes that you need to apply your pattern to and get done a whole lot quicker. You’re still sitting together and communicating so if there are any cases that don’t quite fit you can both take some time out and discuss the best approach.
This feels like a bit of a cop out, but to summarize, I’d have to say that pair programming is ultimately a tool for effective programming and should be treated as such. Like any tool it is great for some things and not so great for others. Being proscriptive about either pairing all the time, or not pairing at all, is almost definitely not the right solution. Sometimes it’s a good fit, sometimes less so. Personally, while I think it can be awesome, I don’t want to do it all day every day.