Pair Programming - A Skills-Based Approach
Pair Programming
Pair Programming is a technique where two programmers work together at the same workstation. To me, good pairing looks a lot less like a driver/navigator paradigm and more like two people having a conversation through multiple mediums. Similar to mobbing, pairing can be a fantastic way to improve quality and throughput while simultaneously accelerating learning.
Given pair programming is a good way to accelerate learning, I can’t help but wonder if there are more or less effective ways to approach pairing for learning. To help reason about this, let’s take a look at a commonly known model for learning.
Dreyfus Model of Skills Acquisition
The Dreyfus Model is a model of skills acquisition, I believe can be well used for consideration in pairing.
There are five stages to the Dreyfus Model - Novice, Advanced Beginner, Competent, Proficient, and Expert. According to the model, during the acquisition of skills, people pass through these stages.
Each stage represents a need for a different form of information, instruction, and practice. For example, a novice needs information about how (not why), specific step-by-step instruction, and non-varied practice. Whereas proficient needs more information about why, little if any instruction, and the opportunity to practice through exploration and experimentation.
Novice
A novice has little to no experience in the given context. They are generally focused on how and benefit from contextually independent snippets that can be practiced without necessarily understanding why they work the way they do.
Think about someone who can follow a recipe but has little understanding of why the recipe works. If you asked them to taste the cookie batter and add more sugar if necessary, they wouldn’t know how to judge. This is true for a Novice in programming as well. For example, if you asked them whether or not the code they were looking at was sufficiently readable, they wouldn’t know how to judge.
As novices readily rely on recipes or detailed instructions, then they tend to blame the instructions whenever something doesn’t work out right.
As a novice gains experience by following recipes, they start to develop more skills and a better understanding of how things work.
Advanced Beginner
An Advanced Beginner has some experience and has a general understanding of how things work in a given context. They are still reliant on step-by-step instructions (how over why), but are now able to judge for themselves which instruction set might work better in a specific situation. They less often blame the instructions and more often select another set of instructions that might also work.
Where a Novice has no means of judging if code is sufficiently readable, an Advanced Beginner can recognize readability and has some means of improving it.
An Advanced Beginner can start to apply simple maxims such as “Don’t Repeat Yourself”. Although, an Advanced Beginner might focus more on structural duplication than logical duplication. A more advanced maxim, such as “Do The Simplest Thing Possible” is still beyond the grasp of an Advanced Beginner.
An advanced beginner gains experience through continued practice by primarily following rules. With increased exposure they grow in their judgement and ability to understand principles.
Competent
At the competent stage, the learner has amassed a number of recipes or patterns and maxims and has improved their ability to understand which applies under what circumstances. This is the primary mark of the competent - they are now able to formulate rules about the patterns.
These rules might be things like, “When the cyclomatic complexity gets higher than 5, look at inheritance or chain of command.”
At this stage, the individual begins to develop a sense of personal connection to the outcomes. Rather than following a limited series of known steps because someone else showed them how, the competent individual knows a great number of ways to solve a problem and has developed heuristics around what to use when. These heuristics are a result of personal judgement, leading to a sense of personal connection to the outcomes.
A Competent individual gains experience through continued practice by trying different known solutions in differing contexts, building their own set of heuristics. As the heuristics improve, their decision making improves.
Proficient
At the proficient stage, the learner moves from heuristics to intuition. The learner develops a sense of what is going to work well as the heuristic moves from executive function to limbic pattern matching. The rules are being internalized.
This intuition for the details allows the proficient individual to focus more on the big picture as they start to not only think about outcomes, but about broader goals such as architecture or business impact.
As proficiency advances and heuristics are internalized, learning moves away from rote steps and is accelerated by experimentation. It becomes increasingly important for the proficient individual to break free of rules and heuristics and thoroughly explore the space.
Expert
At the expert stage, the learner is now acting almost entirely from intuition. An expert knows what is and is not important without thinking about it. They know what to focus on and what to ignore. Decisions are more readily made with little cognitive effort as intuition is now the primary means of decision making.
For experts, teaching can help to clarify their thinking and further deepen their intuition. At this point, it can be helpful to slow down and think deliberately about your intuitions. To decompose them into fundamental thought and find ways to explain them to others.
Progression
According to the model, people go through these stages for each speciality they learn. For example, a developer learning Java will go through these stages (or at least some of them). When that same developer learns Go, they will again go through these stages, but very likely at a faster rate. We are not only able to draw from prior relevant knowledge, but there is some evidence that as we learn, we learn how to learn. So each new skill, be it another programming language or some other discipline entirely will be easier to pick up as we acquire skills.
Pairing and Dreyfus
It might be helpful to think about the Dreyfus Model when considering the composition of pairs. Pairing people with others in or adjacent to their stage allows for continued learning without creating a gap large enough to frustrate the pair members. A proficient would likely pair well with a competent, proficient, or expert, but might feel quite encumbered or frustrated if paired with a novice. This is, of course, a gross generalization as there are many other factors, but it is still a factor worth consideration when formulating pairs.
Perhaps the worst pairing is a novice and proficient. Proficient are breaking free of rules and heuristics and developing an intuition. To learn and grow, proficient need to experiment and test the boundaries they’ve always accepted whereas novice benefit greatly from the boundaries.
One exception to the adjacency “rule” may be a novice to expert pairing. Here, the dynamic changes. For an expert to continue to learn, they need to teach. So we move from a collegial interaction to a coaching interaction where the expert is actively coaching the novice. Done in a more explicit way, for limited time periods and where the roles and relationship are clear, this can be a positive experience for both participants.
As a Manager
While this can be helpful, please don’t use this theory as a hard and fast set of rules. Instead, consider it as you look at team dynamics and how pairs function. If you have no issues, there is no need to “fix” anything. If you do notice tensions and it appears there may be a connection between the skill level of the pair members and the tensions, then consider encouraging adjacency in the pairs. And if you have a gap in the team - say a team of two novices, one proficient, and one expert - consider hiring an advanced beginner.