"It is the long history of humankind (and animal kind, too) that those who learned to collaborate and improvise most effectively have prevailed." – Charles Darwin
One aspect of my time at the Flatiron School that I have greatly enjoyed has been getting to program with other members of my cohort. The curriculum includes both smaller "pairing labs" that last a few hours and larger pair projects that span four to five days. Both styles have given me a taste of what it will be like to work in a team development environment, and also have been immensely beneficial to my learning and fluency with many concepts. It has been interesting to work with people of different personality types and technical strengths. Pair programming also has challenged the stereotypical image I used to have of engineers locking themselves in a dark room alone with a can of Mountain Dew at 2am.
While these pairing labs and projects have been great so far, I've found myself interested in how to optimize my own efficiency and performance when working in pairs. I have also wondered whether pair programming has been proven to be more effective than individual work. These questions have led me to conduct additional research on the topic of pair programming, which resulted in this blog!
At a basic level, pair programming is the agile technique of two people sitting side by side while developing software on one computer. In most pair programming scenarios, one programmer (the driver) writes code while the other (the navigator) reviews each line as it's typed. While at face value it seems that this practice is a waste of resources since it is requiring two people to complete a task that one could do, studies have shown that pair programming has a significant impact on engineering and organizational effectiveness.
In a study at the University of Utah, students with no exposure to pair programming were assigned three tasks to complete in pairs, with 1/3 of students working on their own as a control group. As you can see from the graph below, after the adjustment period shown in first program, the paired students only spent about 15% more time than the individual students.
Offsetting the increased man-hours spent on pair programming, the code produced by the pairs had about 15% fewer defects than the individually developed code (see graph below). Since the average bug takes between four and 16 hours to resolve, the benefit of pair programming to reduced bugs would outweigh the cost of additional man-hours in most projects.
Having never heard of pair programming before starting at Flatiron, I was initially skeptical when I discovered we would be doing so much of our work in pairs. I thought it would hinder my learning to watch someone else do the work 50% of the time, and was worried that communication would be difficult. However, this uncertainty has gradually faded as we have progressed through the curriculum and gotten more practice working in pairs.
The study at University of Utah reflected a similar sentiment among new pair programmers. The graph below shows the results of surveys of both the student pair programmers and professional pair programmers. It is clear that most of the programmers preferred to work collaboratively.
Another effect of pair programming is an improved design quality of the resulting program. In the University of Utah study, the paired programmers finished their projects with a higher quality than the individuals and also implemented the same functionality as the individuals with fewer lines of code.
There are several styles of pair programming that fit different scenarios and levels of experience between the teammates.
Driver-navigator is likely the most widely-used style of pair programming. The analogy is relatively clear: one member of the pair acts as the "driver", doing the typing, ensuring the mechanics of the code are in place and any obstacles are avoided; the other member plays the part of the "navigator", checking for mistakes, and thinking big picture about what goals must be accomplished and the overall architecture of the project.
The driver-navigator style works well with either two experts or an expert-novice pair. In this situation it is best for the expert to be the navigator and the novice to be the driver, to prevent the novice from merely observing while the expert assumes both roles.
This style is similar to driver-navigator, but the navigator takes over more of the tactical roles from the driver. In backseat navigation, the driver still handles the keyboard and typing, but the navigator dictates syntactical instructions, such as what name to call a variable or what specific method to call.
The backseat navigator style works best with a novice as the driver and expert as the navigator, allowing the novice to learn by doing.
Another style of pair programming that is often use in development is ping pong pairing. In this pattern, the first person writes a test that is currently failing, and the second person gets the test to pass. Then the second person writes a failing test and the first person gets it to pass.
The benefits of ping pong pairing are that it enables roles to switch frequently and forces engineers to pay attention to both the coding and testing aspects of development, gaining familiarity with TDD in the process. This style of pairing works best with two experts, especially if they are also experts in TDD. But it can also work well with novice-expert pairing, and novice-novice pairing, to give beginners practice with writing tests.
This is still more of an unofficial style of pairing, but it is likely the future of pair programming. As more development workspaces shift towards remote and global environments, and screen sharing technology becomes ubiquitous, distributed pairing continues to grow in prevalence.
Distributed pair programming involves both individuals working via a real-time collaborative editor, shared desktop, or remote IDE plugin. Distributed pair programming benefits from the flexibility of being in separate locations, but introduces new difficulties that come with the loss of in-person communication. This can make remembering which programmer has the role of driver ambiguous at times.
Ultimately, it has been inspiring to learn and experience how much pair programming has been emphasized both at Flatiron and the larger developer community. I look forward to continuing to refine my pair programming skills and learn from my colleagues!