Pair programming is a recurring subject in the tech industry: some hate it, some love it. But in my experience, most haven’t had a chance to properly experience it.
I’ve worked with multiple teams and organisations over the years and found that I enjoyed pair programming, within limits, when done well. Here I’ll attempt to share tips on how to make the most of pair programming, and hopefully, you’ll give it a try.
ℹ️ Note: here I’m focusing on remote teams because that’s most of my experience. Pair programming for in-person teams is a different story but most of the content here still applies.
Why Should Your Team Even Consider Pair Programming? #
Let’s first talk about why your team should even consider pair programming.
Indeed the initial reaction of most people (and this may be your team lead or manager) is that it will be a waste of time. Two developers working together don’t write code twice as fast so your team will be losing in velocity. I won’t argue that’s not the case in the short-term, but in the long-term pair programming provides a great return on the invested time in a few key areas:
- Knowledge sharing
Are people working in silos? Are you worried about the bus factor? Then pair programming is a great way to break boundaries between individuals. - Long-term thinking
Working in pairs, you’ll tend to reflect more about the code you write together, take other development practices into account and better consider edge cases. You may not feel the value immediately but what you produce together may be orders of magnitude faster (and cheaper) to maintain in the long run. - The best code reviews, without code review
The code written in a pairing session can usually considered as reviewed by a peer, so you’ll be able to skip the formal code review step. Plus you’re getting a higher quality code review because the review was done in real-time, within context. - Two brains are better than one
With multiple people working on the same issue, you can bring multiple expertise, knowledge and experiences together. When it comes to tackling a complex problem this can make a huge difference in productivity. - Building up skills
Whether you’re a seasoned developer with tons of experience learning about the latest editor plugins, or a junior first confronted with a design pattern, pair programming will inevitably enrich your skills. Those skills will stay with every individual and increase the overall proficiency of the team.
When Should You Not Use Programming? #
- To complete a boring task
Pair programming is best applicable to complex tasks. It doesn’t shine on tasks that require little thinking or when the solution is well known and ‘just’ needs to be written. - On auto-pilot tasks
If you have to complete a task you know exactly how to approach and could almost do it on auto-pilot, then pair programming will only slow you down. (If you need to share knowledge, consider recording a screencast instead). - For Rubber-duck debugging
Rubber duck debugging is a great habit and you should use it in abundance, but this doesn’t justify a pairing session. Talk to someone available at the time, your pet, or an Overleaf duck instead. - To have someone else do the work for you
You are confronted with a boring/difficult/annoying task? Don’t be tempted to jump into a pairing session just to have your teammate do the work. - When you’re tired
Pair programming is draining. Don’t start if you’re not fresh.
How to Get the Most out of Your Pairing Session #
By now I hope I’ve convinced you to give pair programming a go. However, make sure you do it well, or you’ll waste your time, have a negative experience and won’t do it again.
ℹ️ Most of the advice applies to a pair but this can be adapted for a small group of three or more, although I find there’s a diminishing return with an increased number of people in the group.
1. Create a Pair
That’s an important step (after all, “pair” represents 50% of the words in “pair programming”).
Usually, the type of teammate you’ll choose depends on what you want to get out of the pairing session.
Here are some good questions to ask yourself:
- do you want to share knowledge with a specific teammate?
- do you want to get help from someone with a specific expertise?
- do you want to work with someone with more seniority?
- do you want to get exposure to an area of the codebase you know little about?
- do you want to help a more junior teammate level up their skills?
Answer those questions and ask the relevant people if they’d be happy to pair with you. You can also ask multiple people and let the most motivated reply.
⚠ Avoid being pushy and let motivated teammates volunteer. The last thing you want is to force someone into a pairing session: that will be a waste of time for everyone.
2. Pick a Time
Pick a time that works well for everyone, depending on their calendar, timezone, habits, etc.
💡 At a previous company we used Donut to create random assignations between devs every couple of weeks, which worked well for us. Important point: participation wasn’t mandatory.
3. Define Roles
ℹ️ Experienced pair-programmers and teams may skip this step but it’s good to keep those principles in mind.
The Pilot-Navigator Model
Think of your pairing session as being at the helm of a ship on a sea voyage (yes, sounds fancy!): you have a goal, a crew, and crucially every member has a distinct role.
In our case, we’ll want to assign the roles of pilot and navigator
- The pilot
The pilot stirs the ship. They are focused on the immediate task at hand: writing the code, worrying about the syntax, calling the APIs, checking the results and otherwise ensuring the code is taking shape. - The navigator
The navigator ensures the ship goes in the right direction and avoids reefs. They think about the big picture: checking documentation, researching alternatives, worrying about the edge cases.
During the pairing session, the pilot writes the actual code while the navigator suggests what do to next.
Why does this work so well? The pilot can write at a great pace as they don’t worry about edge cases, optimisations, traps, dead-ends, etc. It’s the navigator’s role to think about all that while their brain is free from the implementation details.
That model is quite powerful as it makes the best use of our brain’s 2-systems thinking (a concept widely popularised by Daniel Kahneman’s book Thinking, Fast and Slow).
Be careful avoiding those common pitfalls:
- The navigator shouldn’t be dictating code
As a navigator, don’t spell out everything the pilot should be writing (“new…space…Date…with a capital D…”). They’d better use high-level instruction (“Let’s instantiate a date object). - No one is the captain
The pilot isn’t a monkey with access to the keyboard. They can also suggest, contradict and propose changes. This is teamwork. - Be impatient
Mistakes are inherently part of this technique, so both sides must be indulgent. Yes, the pilot will miss an obvious error case. Yes, The navigator will suggest an approach that evidently doesn’t work. But that’s the point, and it means the method is working well. - Teach
If you’ve got a higher level than your teammate, avoid adopting the posture of the teacher. Be sure to also sit back and let your teammate lead. Who knows, you might also learn a thing or two.
Those roles are not set in stone and it’s recommended to switch regularly. Sometimes there are natural breaking-points to do so but you may want to set a timer.
4. Select a task
Be mindful when deciding what to work on.
First off, the task should be small enough. A pairing session isn’t the time to get started on an epic unless the goal is to define high-level outlines.
The task should also fit both members: don’t start working on an area or with a technology one of the members doesn’t know (that is unless the objective is to share the knowledge).
Don’t start in the middle of a task you’ve been working on, or you’ll have to spend most of your time getting the other up-to-speed.
In practice, I’ve found that semi-obscure bugs usually make for a good task. You can take the habit of tagging such tasks as “pair programming friendly” during planning/triaging, so they are easy to find later on.
💡 When possible, agree on the task ahead of the session so that both teammates can familiarize themselves with the context on their own if needed.
4. Agree on a Goal
How long will the session last? Are you aiming to complete the task or stop at a pre-determined step? What defines success? It’s useful to answer those questions so everyone’s on the same page.
It feels good to complete a task, so in general I’d recommend tackling a task that can hopefully be completed within the time given.
That being said, finishing a task often requires dull, semi-automatic work (rearranging code, writing extra tests, etc.) that isn’t useful to pair on. In that case, it may be best to call it done and end the session early.
5. Get Started
Start talking about the task and make sure you reach a mutual understanding of the problem at hand. Maybe one has more knowledge than the other; this is the time to bring them up to speed.
Draw the outline of a solution and get started on the implementation!
6. Finish on a High Note
Ideally, at the end of the session, you’ve completed a task. Well done!
However whether you completed a task or not, it’s good to take a few minutes to reflect: how did the session go? What was learned? What could you have done differently? What are the next steps regarding the task?
Discuss together and make sure you’re parting on a high note.
Extra Tips for Your Pairing Session #
- Talk, talk, talk
Talk about what you’re about to do, what you just did, why you did it that way, what you’re looking at on your own, what idea you’ve just had. Talk a ton so you are always both on the same page. - Take breaks
Pairing is draining. Take regular breaks. - Stay focussed
There’s nothing worse than talking in the void of someone checking their phone. Stay focused and if you can’t, take a break. - Keep it short
If you must, aim for multiple short sessions rather than a single, never-ending session. - Be kind
Working in real-time sometimes with someone virtually leaning over your shoulder can be stressful for some people. Keep that in mind be clear, be mindful of your words and avoid being judgmental. - Share praise
Make sure you share the praise you’ll inevitably get amongst the pair.
Extra tips for the Navigator
- Follow on your own machine
Open the codebase on your machine and follow along. You’ll be able to check related code without asking the pilot to leave it on their screen. - Don’t oversteer
Give the pilots some time to figure things out as they write. They probably saw that typo at the beginning of the line but didn’t want to stop in the middle of their flow. Let them finish and correct minor things themselves before commenting.
Extra tips for the Pilot
- Slow down
Screen sharing usually lags a bit behind. If you’re writing too fast or jumping between lines, functions and files rapidly, your teammate will have a hard time following, which gets quite frustrating. - Share the authorship
You’ll likely get to commit code at the end of the session. In that case, it’s a good idea to add your teammate as co-author.
Tools for Pairing #
In order to make your pair programming session a breeze, you should be equipped with the best tools for the job. Here are a few picks:
Live Share
If you and your teammate are both using VS Code, the VS Code’s Live Share extension is your best bet: it seamlessly integrates into your work environment so you can share your code without thinking too much about it.
Downside: you can’t see the screen so if the code you’re working on relies on a UI, your teammate won’t see it. That being said, you can also share your screen.tmate
If you and your teammate both work within a terminal (using Vim or Emacs for example), then tmate does a great job at sharing your environment. Similarly to VSCode’s Live Share, this doesn’t share anything else outside the terminal.Tupple
Focused only on screen-sharing, Tupple is the best tool I know of when it comes to that: it’s fast, crisp and responsive. Tupple comes at a non-negligible price, but if your team is serious about pair programming then I would encourage you to give it a go.Pop
Back in the day, Screenhero was the one and only tool for pair programming. To many people’s dismay, the tool was bought by Slack and integrated into their video call offering, but many will tell you that Slack’s integration is not as good as Screenhero was.
Pop is a new tool from the Screenhero founders. For some reason it’s currently completely free, so give it a go.Meet, Zoom, Slack, Teams, etc.
Nowadays, all the tools you’d use for video calls boast a screen-sharing option. It’s convenient as it there right where you need it, seamlessly integrated and already paid for.
However, those tools are not primarily focussed on screen-sharing for devs and you won’t get as nice of an experience as you would with a dedicated tool.Web-based online real-time editor If your stack allows it, you could choose to work together on an online editor, where you’ll be able to collaborate in real time.
My top picks are Github’s Codespaces and AWS’s Cloud9.