An introduction to pair programming techniques and etiquette

As you might have noticed, I feel strongly that pair programming is good for teams.

It can be daunting at first, but there are a handful of tips that I’ve consistently seen boost its effectiveness for newcomers.

When you’re done reading this post, I highly recommend that you check out Tuple’s guide to pair programming.

Fair warning...

I’m a shameless Tuple fan.

It’s a fantastic tool for pair programming. I’ve spent hundreds of hours using it.

I can confidently say that it’s the best tool for the job.

It costs money, and it’s well worth it.

Before we dive in, I’ll let you in on a secret: what I’m about to describe here extends beyond just programming for me — these principles guide the way I prefer to collaborate on most things, whether that’s coding or cooking a meal.

Format

Believe it or not, there are several different formats for pairing.

Personally, I like the driver/navigator pattern, which is a lot like rally car driving.

One person, the driver, is doing most of the active coding. They’re “steering the car”, so to speak — maneuvering through the terrain that’s immediately ahead.

The other person, the navigator, is “looking at the map”. They’re thinking about the larger plan and keeping track of which step you’re currently on.

As Tuple’s guide points out, the navigator might suggest higher-level points like possible edge-cases, refactors, etc.

You should trade roles roughly every 45 minutes.

Two keyboards, two mice

Pairing is significantly better when each person has the ability to click and type.

This allows you to collaborate more seamlessly, jot down quick notes, fix a quick typo, etc.

When in-person, take the time to set up a keyboard and mouse for each person. Pair on the same computer.

When remote, use tools like Tuple to give each of you these abilities. Pairing over Zoom screenshare is just not as good.

Etiquette

A critical part of hitting your stride while pairing is having good etiquette.

My advice, whether you’re new to pairing or not, is to read through Tuple’s page on Pair Programming Antipatterns. Most of my etiquette advice boils down to avoiding these.

Here are my top three highlights:

1. Don’t call out errors too quickly

Give your pair a moment to notice and fix their own errors.

Jumping on them too early is annoying and breaks up the flow.

2. Code with them, not through them

Sometimes I see folks dictating code to their pairs character by character.

That’s obviously not ideal. It reduces the other person’s agency and is inefficient, both of which are draining.

Instead, describe your ideas as high-level concepts that your pair can implement.

You can think of this as giving declarative instructions, not imperative ones.

Example

As a non-technical example, imagine we’re cooking a meal together.

I’d rather you say: “Hey Dan, can you handle cleanup?”

Instead of: “Hey Dan, put the onion scraps in the compost bin.” And then: “Now wipe down the countertop.” And so on.

I generally try to start with strategy-level discussions upfront.

And even in my more tactical comments, I try to avoid being overly nitty-gritty.

Remember: You’re coding with your pair, not through them.

Here are some examples of things I might say while pairing.

Each of these is more tactical than the last, while leaving room for my pair to implement it themselves. (or to propose an alternative path forward)

I think we can treat this as a recursive backtracking problem. We’ll probably need a way to determine if a boardstate is valid.

Let’s give ourselves an easy way to print the boardstate for debugging.

We know all of the pieces that exist and which ones are currently on the board, so I think we can simplify our solution by deriving the “remaining pieces” rather than passing them around in a data structure.

Tooling

The “two keyboards, two mice” rule helps a lot with avoiding overly-nitty instructions.

If you’re able to quickly fix typos or point something out with the mouse, you’ll be less likely to encounter this: “Ah no, a little bit below that — keep scrolling...”

3. Get on the same page

Before you begin, discuss your high-level goal and any relevant context.

For example:

The dashboard page is slow, and our goal is to investigate why. So far, we’ve ruled out slow database queries.

Having this shared high-level goal is critical.

Next, build a roadmap together.

This is what the navigator will use to keep you on track as a pair.

Example roadmap:

First, we’ll look at the network tab to see how many requests are being made and how long they’re taking.

Next we can use the React DevTools to profile the application and look for components that are taking forever to render.

Write it down and put it somewhere that you can both access easily. (a piece of paper, a google doc)

From there, it’s your job to stay on the same page by checking in against your plan regularly. This is mostly the navigator’s job, but both of you can do it.

Okay, so taking stock here: we noticed that the network requests are relatively fast, but we’re making a lot of them.

There might be an issue with how and when we’re fetching the data in the component. Let’s explore that next.

In addition to this, staying on the same page means making sure you both understand what’s happening on a more fine-grained level too.

For example, if your pair isn’t familiar with a concept or language feature that comes up, you should help them understand it before moving on.

Hey, I’ve never seen nested list comprehensions like this. Could you explain this to me?

Yea, happy to do that. And honestly we should just refactor this — I try to avoid them because they’re hard to read.

Conclusion

Done properly, pairing is both fun and productive. You can hit a flow-state with your pair and, often, move faster than you would as individuals.

Good tooling and etiquette goes a long way. It will feel much more natural.

Also, remember that it’s a skill, so don’t beat yourself up if you need some practice.