Let’s set the record straight right away.
1. I work for ThoughtWorks.
2. I enjoy pairing (sometimes), and I think it’s valuable (usually).
3. You don’t have to pair program 100%. It is a tool, not a requirement.
The software development community has been raving over the benefits of Pair Programming for a while now. For a team that’s not currently employing this practice, I strongly encourage you to trial it. Follow the wisdom given by others in their articles about implementing and optimizing the practice. [This article assumes that you or your organization has at least adopted Pair Programming, and may be heavily dedicated to it.]
Why I’m writing this
Some of the teams I've joined adopted pairing, and then never stopped to look at it with a critical eye. We never asked ourselves:
- Is it providing the productivity and quality benefits we hoped it would?
- Is everyone on the team happy?
- Are there experiments we could try to make it more effective for us?
Many teams will make faulty assumptions, such as “everyone prefers pairing,” “pairing in the same way is the best choice in all situations,”or “pairing is a required practice.” This article takes a look at some variations and considerations when looking at the standard pairing model, which take into account the following factors: experience/skill level, remote team members, strengths of other team members, and personal preferences.
Divide and Conquer
The Divide and Conquer strategy means two people working on the same thing, but breaking it down into separate, mostly independent tasks and divvying them up.
The pair works side-by-side, which gives them a high-touch environment when needed. They can pose questions to each other, get on-the-spot reviews, check-in periodically, or ask for help. If some task is taking a long time, they can switch to a more classic pairing structure for that part. When all the tasks are completed, the pair reviews everything together. This helps ensure that there is no siloed knowledge.
This works well when...
I’ve had success while working on something that neither person is very familiar with, such as exploring a brand new library or technology. The traditional pairing model breaks down in this type of situation. How many developers does it take to Google something for a while? What if one person reads faster than the other or likes to read and absorb things in themselves first? With the Divide and Conquer strategy, both people can explore different parts of a problem space simultaneously, and then educate the other later. Learn and then teach.
Two senior developers can use this strategy effectively too. It requires trust of the other person, and a lot of collaboration to stay in sync though. Late integration becomes a risk if the tasks are closely related and the pair diverges too much. Communication and collaboration is key.
Finally, consider this strategy when you have remote team members as it lessens the reliance on real-time remote pairing. Remote pairing technologies have come a long way, but the experience can still be very painful, especially when one person does not have a great Internet connection.
This pattern has two people working as individuals on separate things, while providing support to each other at regular intervals.
The keys here are proximity and frequent check ins. At least twice a day, the “pair” hooks up to discuss progress, review code, get advice, etc. The pair physically works side-by-side, so each person still has a pair to go to when things come up.
This works well when...
Consider using this when an Advanced Beginner dev and a Competent or Proficient dev are paired up. (Note: These are three of the five stages of the Dreyfus model of skill acquisition. Chapter 2 of “Pragmatic Thinking and Learning” has a great explanation of this journey from novice to expert, applied to programmers. ) There are benefits on both sides. The more experienced developer has a reprieve from teaching and mentoring. The less experienced dev gets space to learn on their own, experiment, and fail in a safe, supported environment. It’s important for the senior dev to always be available to help out the more junior person so that they don’t get stuck. The pair should work together to establish how often they will check-in, and when interruptions are allowed.
I’ve also applied this on a small team of junior devs (Dreyfus model novice and advanced beginner) with a couple seniors who are strong coaches/teachers. We would often float around the team, checking in with each junior who is working pretty independently, offering advice and answering questions. This was great for me, because I was was not stuck in teacher-mode all the time. I still got the chance to get deep into the code too.
A Warning on Novice Pairs
A pairing of novices can be a gamble. On one hand, they could have a great experience. They work through their problems, making mistakes and learning from them, and they accomplish their goals. More often though, I have seen a blind leading the blind scenario. They spend hours frustratingly spinning their wheels, Googling the wrong questions, debugging the same failing test over and over - only to have another team member come by later and discover their mistake in five minutes. Learning experience or time wasted? For all these reasons, and more, I do not recommend novice pairing in most situations.
In the real world, it really doesn’t make sense to “prevent” inexperienced devs from pairing. Instead, you can lessen the risks by being deliberate about your pairing strategies. Here are some considerations if you find yourself on a team with a high percentage of novices and advanced beginners:
- Rotation. Rotating pairs at a high frequency may not make sense. The pairs may not be making much progress on their tasks. Collective context sharing is important, but rotating too quickly may not causing devs to spend most of their time trying to gain context on the next thing.
- Trust. Work hard to build a safe environment and a team culture. It’s normal to not admit when you don’t know something. It’s normal to not ask for help, even when it’s offered. Establishing trust within the team takes effort.
- Time-boxing. Encourage people to time-box their tasks. Inexperienced devs may have a hard time knowing how long to spend on something before asking for help. Tech leads can help them establish appropriate time boxes.
Straight Up Soloing!
Don’t worry, if you do code without a pair sometimes, the world will not end. Your team will not implode. Your code will not catch fire. It’s ok. If anything, building some solo working time into your team’s practices will show everyone that it is acceptable. Or, because some devs have always paired, having solo time will allow them to experience the pros and cons of it. I advocate experimentation and finding the processes that work best.
This works well when...
Working alone can be appropriate when repeating a well-established pattern. Implementing yet another simple CRUD controller for your Rails app? Solo it. Forgot to do a null check and now there is a defect? Solo it to make the 1 line (+ 1 test) fix. I would strongly suggest using code reviews here though. However, too much soloing time is also not a good thing, especially for novice or advanced beginners. Be careful here.
Finally, soloing speaks to the human side of programming. Most developers love coding and solving problems. Sometimes I simply want to put on my headphones, pump up the volume, and code. There is nothing wrong with that.
The last one I’ll mention is maybe the coolest one. Mobbing is pairing to the extreme. It means having many people, often an entire team, working on the same thing at the same time. Mind. Blown.
If your team often works independently, I recommend adding these to your team practices to keep rapport and cohesiveness high.
There are a bunch of variations, here are a few:
- Code Jam: This is the most unstructured option. A code jam is usually a time-boxed activity focused on a specific task, such as a refactoring. Put your team in a room, plug in a monitor or projector, get at least 1 keyboard and mouse. 1 driver, everyone else navigates. Rotate drivers regularly. Feel free to play with the format though.
- Randori: This is a variation of a Code Jam with a specific rotation structure. In the randori style, two people pair, while the rest of the team observes. After a short amount of time, 1 person rotates out of the pair, and 1 person rotates in. Cycle through the entire team.
- Mob Programming: Now I have never followed this pattern, but I think it's very interesting. The gist of it is the entire team works together…. all the time, every day! No soloing. No pairing. Just working as a team all day every day. Intrigued? This talk describes it.
Trying to stick to any of the patterns presented here at all times would probably not be a good idea. But, take some Traditional Pairing, mix in a dash of Soloing on Fridays, add a Mob Coding session once a week, and switching to Supported Soloing when the time is right sounds like an effective team pairing dynamic to me.
Many equate Pair Programming to Agile or Extreme Programming. While It is one of the core practices associated with those methodologies, I’ve seen many teams adopt pairing blindly, making it the default, and never reflecting on it. Instead, I try to always keep in mind this quotes from the original Agile Manifesto principles:
“At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.”