February 10, 2023
In the mid-aught halcyon days of Agile and eXtreme Programming, we were innovating and practicing development techniques that led to better code, increased test coverage, and superior knowledge transfer within the team. Anecdotally, however, it seems many of these practices have now faded from common use without having been replaced by more efficacious alternatives. In this post, I’d like to talk a bit about pair programming in particular, and why the practice should be revisited by today’s development teams.
Presumably, many readers might benefit from an introduction or refresher on pair programming. Briefly, pair programming is the practice of two developers verbally and collaboratively working on a shared coding task typically in person on a single workstation. There are numerous benefits to this arrangement over solo coding, but here are a few of the highlights:
Typically, one pair member will operate as the driver with hands on the keyboard. The other will serve as the navigator, though these roles can swap even moment by moment as necessary. This arrangement offers opportunities for the navigator to think about upcoming decisions while monitoring the code being produced simultaneously by the driver. Optimally, it’s the more junior member driving so that the more experienced member is forced to ensure that their partner fully understands all the code being written. It is important to note that dictation of code by the navigator is discouraged. They should describe the behavior and assist with syntax but allow the driver to write. Both members should understand the code and agree on the technical solution being implemented for the problem space.
My first real Java development job was on a small product team that used pair programming to write 100% of our production code including configuration and build artifacts such as Ant scripts (these were pre-Maven days). Each day comprised three scheduled 1½ hour pairing sessions–one in the morning post-standup and two after lunch, separated by a 15-minute break. It was common for us to switch pairing partners midday to help ensure that every team member was current on all the stories being worked on in the sprint. Having joined as a very green Java developer, I couldn’t imagine a better environment for rapid learning.
My next job found me at a consulting firm that committed fully to Agile and eXtreme Programming. So dedicated was the company to the cause that they designed the new office space with these practices at front of mind and with input from the development teams. One of our leads came up with the idea of hanging drop cords from outlets on the ceiling for network and power that would allow individuals, or even teams, to reorganize the entire workspace in only a few minutes. This concept confounded the local authorities who had never seen such a thing, and some back-and-forth was required to come up with a proper solution that could pass code. The result was a resounding success. Desks were on wheels and each workstation had two monitors, keyboards, and mice allowing a pair to quickly switch roles without friction. Teams, workstations, and team spaces were therefore configured for maximum collaboration and flexibility.
At one point, and against our better judgment, we hired a “rockstar” developer. You may know the type–the maverick who produces a lot of code but may not play well with others. If you’re lucky they are disciplined and produce high-quality code and tests, but at worst you get neither of those plus a prima donna. In our case, we lucked out. We slowly managed to extract the keyboard from his hands (with which he typically coded at 100+ wpm) and trained him to operate as a navigator. His hands would fidget, and his knee would bounce as he learned to restrain himself from taking over control from his driver. He learned to communicate his ideas and convince others–as well as to be convinced–rather than always plowing forward on his own. In the end, he became a consummate team member declaring at one point, “this is the first time I’ve ever respected my coworkers”. I believe the difference was that pairing forced him to listen to his coworkers and convince them of the merits of his ideas rather than any superiority of our talent. Pairing serves as a forcing function for communication which may be its greatest asset.
For reasons I can’t fully explain, pair programming later fell out of fashion. Pairing is a discipline best learned through practicing it, and I’ve found that many developers today never really have. Often, they have only ever–at most–sat with another developer for a debugging session and never treating pairing as a skill to be honed. Now that there are fewer practitioners in the wild it is more difficult for the practice to propagate. In recent years when I’ve attempted it, I’ve often been faced with some resistance.
Recently, a team member of mine was struggling with a coding task, and when I offered a pair programming session to help resolve it, she balked. After another day of limited solo progress and with a weekend to reflect, she reconsidered. We spent several hours the next week pairing virtually and we worked through the impasse. Afterward, I asked for her impression of the pairing experience and she said, “It wasn’t what I expected. I thought it would be like an interview.” I should acknowledge that in this scenario there is a power dynamic at play in that she reports to me, but when properly implemented pair programming is an equalizer. In fact, some people even refer to it as peer programming. Pairing should be ego-less even though a disparity in experience between members is common.
At Nortal, we understand that whiteboard interviews don’t reflect day-to-day reality and use pair programming exercises exclusively in our process because of the insight it provides. Last year we had a Solutions Architect candidate decline to continue their interview loop when their recruiter told them that there would be a pair programming exercise. Several factors likely impacted their reticence, but one that I’ll suggest is that often Solutions Architects are not daily coders and can fall out of practice. Still, we need to know that our technical employees are technically capable even if they are primarily architecting systems rather than writing production code. The recruiter brought up at our weekly staffing meeting that we were going to lose the candidate since they wouldn’t participate in the exercise. I suggested that the recruiter explain to the candidate that the purpose of the exercise wasn’t to lay an algorithmic trap or test arcane computer science knowledge. It is to get a feel for how they might collaborate and participate in the give-and-take of ideas. It is a way to evaluate their ability to assert or defend a position and how they react when presented with a better alternative. It turns out that pair programming can reveal much about one’s character and collegiality. Reframing the exercise convinced the candidate to follow through after all, and they are now a productive team member at Nortal.
Research has shown that two developers pairing on a task take 15% longer than if they were working on two separate computers. Why 15% and not 100%, you ask? A superficial assumption might be that as a pair they would take twice as long to write the same amount of code since half as many computers and hands-on keyboards are in play. However, the statistic shows the pair is performing more efficiently together, debunking the assumption. One potential explanation for this is focus–there’s less temptation to flip to email or Slack or shave yaks when pairing. Another is a pair coding together can confer and select an optimal solution before any code is written. Also, while the driver is coding an agreed-upon solution the navigator has headspace to consider other implementations and considerations before change becomes prohibitively expensive. Meanwhile, in addition to managing distractions, a solo coder may require several attempts at an implementation to discover an optimal solution which may involve substantial rework.
The same research shows that pairing results in significantly reduced bug counts–as much as 15%. This can be explained by the instant code review offered by an engaged navigator. Rather than a review (often cursory) of a pull request by an uninvolved party, the navigator is intimately aware of the purpose and design of the code in question. As well, since the pair has presumably implemented the best of the ideas produced by the members, algorithmic–yet syntactically correct–errors often can be caught prior to the code being committed to source control and potentially making it to production. I challenge the reader to identify another practice that can reduce bug counts by 15%. This is a massive benefit of pair programming.
It bears repeating that pair programming is one of the very best mechanisms for knowledge transfer within a team. By fully engaging junior and senior team members together, throughput is maximized. A junior member need not be concerned about interrupting a senior member with a question–as might happen with conventional solo programming–when the two are working closely together. This can significantly reduce time wasted when more timid developers are reluctant to seek help.
There are many notable benefits to pair programming, among them team knowledge transfer, reduced bug counts, and a process for involving multiple members in unit-level architectural design decisions. Pairing is a discipline, however, and requires practice. Many developers who haven’t tried it find the idea off-putting until they have an opportunity to experience it for themselves in a supportive setting. Unfortunately, the waning of the practice means fewer experienced practitioners are available to train up the next generation. Companies seeking the benefits promised by pairing can benefit even if they opt not to commit to coding 100% with the practice.
To learn more about Nortal, visit nortal.com.