Impressed with Pair Programming

Just what is pair programming? Extreme Programming defined it as two developers who team together and work on one computer to develop user stories. Does that work?

That was my question last year, and I decided the only way to truly understand was to pair program myself. I don’t code much these days – like so many techies who’ve moved up the management ladder and away from programming, I regret having neither the time to spend at the code face nor the up-to-date development skills.

Although pair programming has been around for decades, uptake has been slow in many companies. I’d paired in a few workshops, but never for extended periods or on production code.

With a mixture of trepidation and excitement, I cleared most of my diary for 3 weeks. My pairing partner would be a senior developer who also lacked pairing experience, but came with all the language and environment skills necessary to supplement my rusty code skills.

We joked about how long it would take us before one of us wanted to kill the other one. Half joke, half real fear of putting two strong-willed developers together. Our first project was a small web SPA using .Net Core and JavaScript.

Our process was to write down a short list of tasks (using pen and paper) before starting. We religiously swapped mouse and keyboard every 10 to 15 minutes, if not sooner.

If you’re new to pairing, the idea is that one person drives (i.e. controls the mouse and keyboard and does the typing) and the other performs a navigator role. The navigator directs the design, and helps to spot coding errors.

It quickly became clear that errors are very easy to spot while you are navigating and not typing, but that you need to hold your tongue for the typing partner to complete at least that line of code. Interjecting too often breaks the driver’s concentration. We established the courtesy of only pointing out typos once the driver moved on to the next line and had clearly missed the error.

We also made lots of short written notes. This covered ideas for refactoring, memory jogs for all sorts of issues we wanted to return to, and topics for further investigation. This helped us to maintain our flow on the section of code we were working on, rather than trying to keep too many threads in our heads.

A few hours into our first morning, and many keyboard swaps later, we both agreed that we were mentally exhausted. We’d been flying through the code because one person was always working out what to do next, while the other applied their brain to the typing.

It turns out that typing (ok, it’s also lots of little decisions like method naming and code syntax as well as typing) uses a large part of our brains. The accelerator effect of having a navigator role was that deeper thinking about cohesion and coupling and tests (at a minimum) was happening at the same time as the typing, and we weren’t stopping to think in the same cadence as we would when working alone.

Lesson one was that productivity was increased by pairing, way more than I had expected. This remained true throughout the 3-week experiment, although we did have some low days when we were sluggish and struggled with pairing. Overall, we had more days that were exhilarating and exhausting and satisfying. Deeply satisfying.

Our basic web SPA exercise took us just under 3 days to complete. Code quality was excellent, if I say so myself! We were picking up errors early with two heads engaged in the work. We scored on two fronts – less typos (especially those hard-to-find JavaScript ones), and better defensive coding throughout the app. My partner would think of scenarios that I’d missed and vice versa, so the potential for errors reduced.

Lesson two, therefore, was that code quality was better under pairing by a significant margin. The fact that we were both experienced developers helped, and I’d assume that this benefit will scale with the experience of the pair. A junior pair will be good at reducing unintended errors like typos, but maybe not as good at predicting scenarios for errors. That still needs experience.

So far, we hadn’t had any emotional outbursts or frustrations. Despite our early fears, our egos, experience and drive were meshing to produce better and better results. We took care to use respectful language when debating ideas, and to keep our hands off the keyboard when we weren’t driving.

It’s ridiculous how hard it is not to want to type when your partner is the driver and is being a little slow with a concept! Of course, “being slow” is relative! It’s much easier to see what to do as the navigator and with the luxury of taking a metaphorical step back. Understanding that your partner will also see you as slow when you’re the typing driver, is an important step to being humble.

Lesson three was “how not to be an asshole”. Give your pairing partner the space to solve problems too. Don’t dominate the process, and never grab the mouse or keyboard out of their hands!

Another joyous experience was the cleanness of our solution. We had great debates around code design. This went far beyond the kind of design sessions I’ve done in the past in Sprint Planning (SP2) or similar design sessions.

This was micro design, method by method, test by test. Did we really need that public variable, how could we better encapsulate that concept, was this piece of code not similar to the piece we wrote yesterday? We shared knowledge, experience and thinking to produce code that we didn’t hate at the end of the project. Big win!

That was lesson four: pairing produced a clean, maintainable, working solution that was closer to textbook perfect than most code that makes it into production. Clean code is a Good Thing, and I’ll write a different post to explain that some other day.

Lesson five was all about learning. I refreshed my rusty code skills, but the learning was by no means one directional. I could contribute design ideas and code approaches from the get go, because I came to the pairing with a unique set of experiences.

Once I realized that I had something to contribute, my confidence grew. That accelerated my learning as it was such a positive experience.

In our second phase we worked on technical debt and refactoring for a large C# project, and my learning swung from code to domain issues. A common experience when learning a new system is trying to get help without being a nuisance to other team members. It’s a really negative experience. By contrast, pairing with someone who knew the domain turned a potentially big negative into a non-issue.

I’ve moved from intellectually believing that pairing was a good idea, to a deep connection with the behaviour it encourages and the outcomes that it produces.

My conviction now is that teams should be encouraged to pair all the time.

There are environmental challenges – some desks are too small to allow two developers to comfortably share the space. Armrests on chairs are also a nuisance, and we found ourselves playing chair “bumper cars” a little too often. The ideal office space will need to take the new seating needs into account, for pairing to work long term.

Personalities play a big role – the solo genius is not a useful team member when you want the team to pair. Maybe they never were useful on a team. Software is a creative activity requiring high interpersonal communication skills, and the teams that are successful communicators will do very well when they adopt pairing.

I’ve found three big obstacles to pairing. The first is ego, where a developer either doesn’t want to share their knowledge or believes that they are too good to need to work with someone else. Not sharing knowledge is a big problem for any team, and leads to silos. Address that as soon as you can, because it puts your project at risk.

Believing they are too good to pair is best tackled by pairing them with someone they can learn from. If you don’t have any other strong developers in your team, that might be a red flag. Why not? Is the strong developer taking all the complex tasks and denying the rest of the team the chance to learn? Whatever you find, like a lot of Agile practices, it’s good to identify your issues and start to tackle them.

The second issue is imposter syndrome. This is where a developer has low self esteem, and fears being discovered to be a fraud, or simply not very good. It’s a syndrome, and mostly not true. Pairing will help them to calibrate where their skills really fit, rather than living with the fear of not being good enough. Again, identify the problem and start addressing it in a safe manner.

The final issue I encounter far too regularly, comes from management. This is the belief that pairing will cause every task to cost double, because two people are doing the work that was previously done by one.

There are some great statistics on the cost of finding and fixing issues in code late in the production cycle. It’s very sobering how much of the cost of software occurs after the initial code is written. I’d suggest approaching management with industry stats as well as tracking your team’s defect rate after you’ve started pairing. Metrics are always easier to defend than opinions.

Of course, if your defect rate doesn’t go down, you have another opportunity to review your process and figure out why you are not getting better code quality from pairing. You could look deeper into other Extreme Programming practices like writing unit tests, and also help your team to up-skill in any areas where needed. Feedback is the cornerstone of improving.

I’m giving pair programming a resounding thumbs up. I hope you do too.