Articles explaining pair programming or providing tips to pair program effectively are ubiquitous. If you’re interested in learning how to pair program, knock yourself out with your search engine of choice. This, however, is about pair exploring: why to pair program, or, maybe more accurately, when to pair program.
Remember the three phases of software development.
Before we get to pairing, I think it’s necessary to define the process of software development a bit. I believe you can break down any software development task (and for that matter, almost any complex task) into three phases:
- Discovery
- Implementation
- Production
Discovery
This is all about figuring out how you can do something. The goal is to identify all the reasonable paths you could take to solve a problem and then choose a small number of the best options to actually attempt. This is the phase when programmers might “spike” on a feature, write on the whiteboard a lot, or read documentation.
Implementation
This is where the bulk of the actual coding gets done. The goal is to put your ideas into practice to make sure they really work the way you thought they would (and if they don’t, it’s back to the Discovery Phase for you!). It’s when you might write tests, and types, and interfaces, and schemas, and etc. It’s where your “tracer bullets” get developed.
Production
This is when the final product is made. At this point, you should have worked out all the major details, and it’s just a matter of completing well-defined tasks. There are bound to be some small surprises here and there, but the flux should be minimal. A relatively inexperienced developer could competently handle at least some of the work in this phase on their own.
This is what you’re probably getting wrong when pairing.
Quick, answer this question: Pair programming is most valuable during which Phase?
.
.
.
.
.
.
If you said “all of them,” nice job smart aleck.
Ideally, pair programming would be practiced across all three phases. But pairing a lot is HARD, and it’s generally not sustainable for all of your working hours.
In practice as well as in articles about pair programming, the focus is often primarily on the implementation phase and/or the production phase, citing patterns like Navigator/Driver and focusing on code quality. Even when citing the value of mentorship or knowledge sharing, it’s in the context of removing expertise silos in, or onboarding someone new to, a codebase.
Meanwhile, developers shy away from or even overtly discourage pairing during the discovery phase. And I think this is a mistake.
Optimize for pair discovery.
Discovery is obviously the most challenging phase in which to pair. The problem space is wide open, and complexity is at a maximum. There may be multiple approaches to solving the problem and no clear answer for which would be best.
It pushes communication skills, tests patience, and can even be somewhat awkward. How do you “pair” when the task at hand is just to read lengthy Stack Overflow threads and ponder the true meaning of a Hexagonal architecture. This is often more acute when there is a large difference in experience level between the pair, or when one developer is very early in their career.
All of this is exactly why pairing during the discovery phase can be so powerful. If you can’t pair all the time, it should be concentrated on the hardest tasks, while leaving the long tail for the individuals.
Rethink your terminology.
Instead of Pair Programming, we should focus on Pair Exploring. You and your pair are about to embark on a grand adventure together. Who knows what exciting discoveries await on the roads ahead?
In the discovery phase, having multiple perspectives can open the door for greater creative problem-solving. The need to explain complex concepts to another person strengthens your own understanding. Ultimately, creating consensus on what direction to go builds trust and ensures that you both know not just what you’re doing, but also what you’re not doing and why you’re not doing it.
Don’t get me wrong, I think pair programming is an excellent tool for writing better code and training people to become better developers. But the further you get into the production phase of coding, the less value is derived from the pairing.
Adventurers returning from a long journey may be happy to have someone by their side, but they already know how to get home.
Pair Programming vs. Pair Exploring
To recap, there are three phases to software development tasks: discovery, implementation, and production. Historically, pair programming was focused more on the implementation and production phases. Don’t let the term “pair programming” limit you. Start thinking of it as Pair Exploring.
Pairing is valuable during the other phases as well, but less so as you get further along in the task. At the extreme end, it’s just one person watching another person watching automated tests pass.
Meanwhile, the discovery phase is largely exploration and acts of creation. This is when collaboration is most beneficial, and so that’s when you should prioritize pairing. Front-load your pairing to the discovery phase as much as possible.
Discovery is also the most difficult phase for pairing, which is why you should work extra hard to get better at it. In my next post, I’ll go into several techniques to help you get better at pairing during the discovery phase.