I’ve been working in “agile” teams for several years, and since starting at ThoughtWorks one practice that we always seem to use and promote is pair programming.
I think pair programming is great, for a few reasons:
- Knowledge sharing and avoiding silos or single points of failure.
- Bringing people up to speed – especially for new team members and juniors.
- Building relationships and communication. I found after my first project as a developer, I had much closer relationships with the developers I’d paired with than any of the other people I’d worked with as a BA on previous projects. This makes for better teams.
- Collective code ownership – if you’re not the only one working on the code, you can’t feel too much like you own it.
- Better decision making – by having two people discuss and agree on a solution.
- Faster problem solving – especially in complex systems.
- Promotes consistency of code style and standards, especially if the pairs rotate.
Yay! So should we always pair all the time?
I would actually say No to that. Having spent a decent amount of time pairing, and experienced many eager and reluctant pairs, been the “junior” and the “senior”, on both work and fun projects, I’ve found there are definitely some frustrations.
- It’s exhausting. If you’ve ever done a solid day of development on a difficult project with a pair, you probably came away shattered.
- After working with the same person for a long time, both people stop learning from each other. A lack of rotation also means you still end up with knowledge silos – just made up of two people rather than one.
- Sometimes, pairs are well matched, but more often one person is significantly faster, usually because they’re more knowledgeable about the codebase or the work being done. Over time, this can be frustrating.
- Pairing on simple problems can feel like a bit of a waste. I’ve definitely been in this position towards the end of a project.
- Some people just don’t like pairing. Even I don’t like pairing when it’s all the time.
- I’m not convinced that pairing significantly reduces the number of bugs when you practice TDD and have a good suite of automated tests. The navigator may see obvious errors first, but more often than not the automated tests find the more interesting ones before the code is even checked in (although it does help having two people to solve them)
My last project was a two-person delivery gig. My colleague Hari and I discussed upfront whether we would pair, and in the end we didn’t – for some of the reasons above, but also because some of the benefits of pairing were much less on a two-person team:
- We didn’t really have a complex problem to solve – it was a reasonably simple, small website.
- Six weeks of pairing with me would probably have driven poor Hari insane.
- We were sat directly next to each other and were constantly discussing the project, so we didn’t need to work on the same code to make ourselves communicate or share decisions.
As well as agreeing to talk a lot, share important decisions about the code design, and refactor each other’s code where we saw a need to, we also decided to rotate the stories we were working on to try and avoid any silos or single points of failure.
So how did it work?
In retrospect, I do think it was the right decision. I discovered that I actually enjoyed working alone (which felt like a terrible admission for a while) – although I still prefer to work in a larger team with some pairing, I now believe that developers also need a break from pairing some of the time. It’s a matter of finding the right things to pair on, and the right time to work alone. For us, I think pairing would have slowed us down.
However, at the end of the project, I discovered that there were definitely some gaps in my knowledge around the things that Hari had implemented. We were probably not rigorous enough about recognising when we did need to pair and doing it, and towards the end of the project as time grew tighter we did not swap stories enough. We were pretty good at changing each other’s code, and I think that in general our coding style was fairly consistent – although this was probably the case before we even started working together, it seems to be a ThoughtWorks “thing”!
From a quality perspective, only one bug was reported in UAT, and it wasn’t even much of a bug (calendar starts on the wrong day) – and I think this is because we were pretty rigorous around our automated testing practices, including integration and acceptance testing with Cucumber.
In future, I would still promote pairing but perhaps a little bit less dogmatically than I used to. I want to make sure I continue to use it when there are clear benefits, and especially when introducing new team members or for complex problems. However, I would like to try and ensure developers have more breaks from pairing and that work is organised to allow for that, as well as a good degree of rotation. How often the rotation happens, and what proportion of time is spent pairing versus working alone, I think should always be dependent on the team, the problem at hand and the situation.