When I first heard about pair programming, years ago, I regarded it as a fad and a scam. Experts in the often-fluffy field of software engineering proclaiming the one true way to build software in an attempt to sell books and conferences. That said, I've recently been convinced that pair programming might be really great. Here's why:
- Pair programming helps you become mindful of how you, and others, solve problems.
- The communication loop is tight, instant feedback to your ideas, thoughts, and actions.
- Reasoning about a task, in two different modes, at the same time. Two minds, one goal.
Pair programming seemed to limit control to solve problems in my own way. One of the things I love about programming, and abstract problem solving, is that there are few limits. In my head, pair programming was intrusive and disrupted creativity. It is now becoming clear that the opposite is true. Instead of solving problems our own way, we should strive to solve problems the best way. Sure, you might think you know your hacking tools in and out - but how do you know there isn't some trick to improve your workflow that you're missing?
How do you know the process you use to solve various types of problems is the best? If you have experience, and especially if you were lucky enough to work with a great mentor, you may have picked up some problem-solving tactics. Can you list the tactics you use to solve a problem? I've found that we sometimes are unaware of our own problem-solving process. Next, have you ever spent time testing out the effect each of those tactics has on the outcome of solving problems? That's a lot of data for one person to gather. Not only would you need to record all the observations, but you would need a lifetime to generate enough samples to draw any conclusions.
While conducting a research study to determine what tactics are the most crucial for solving different problems is a tremendous challenge, we can approximate the findings by being mindful and observing others. Each of us have built up an arsenal of tactics, our tricks of the trade, and you can get a snapshot of any engineer's strategy by watching him solve a few problems. How does he start: pen and paper, whiteboard, or straight to code? What next? Writing a test, defining interfaces, or taking a walk?
Becoming mindful of our own and others’ problem-solving strategies is a process that likely never ends. Thankfully, we have mentors, peers, and students to point out steps we take without notice. Consider a student seeing something for the first time, asking why you perform a particular action; or a mentor opening a dialogue to challenge a misstep.
Sharing ideas and intent with other programmers can spark design discussions that lead to clarity and solutions. Great, can't design meetings and code reviews accomplish the same effect? Sort of, but not efficiently. Design meetings work well for only the broadest discussions, the details that begin to drive the design are mostly unknown until there's an implementation. Interlacing design discussion with writing code permits a higher fidelity in the design.
Similarly, distinct code reviews are useful but frequently occur too late. Peer code review should be interactive and occur as code is written, more time is saved when poor decisions are detected early. This prevents scenarios where large commits, perhaps a full day's work, is based on misunderstandings or bad engineering. When pairing, the partners should be thinking out loud. That verbal communication can prompt a design review to occur before any code is ever written. However, actual reviewing of code is also important to catch any assumptions or bad choices that are not verbalized.
This hypothetical benefit of pair programming excites me the most. When people talk about having awesome pairing experiences where the pairing team has momentum and flow, I think they are taking advantage of what I call dual modes. In most pair programming literature this concept isn't given a name, instead they talk about two roles: driver and navigator. The driver is whomever has the keyboard and the navigator is the other. These names are deceptive, they imply there is only one active role, the driver, and then some pansy navigator trying to follow the action and pointing out spelling mistakes. Sounds lame.
If either of the roles should be considered more active, it should be the one not banging on the keyboard. Instead of a driver and a navigator, there should be a grunt and a commander. The grunt is trying to figure out how the task can get solved given a limited set of assumptions. Those assumptions enable the grunt to not worry about the big picture and focus on only implementing the current task in the best way possible given the assumptions. The commander is the mastermind, she should be providing the assumptions, revising them based on reports from the grunt, and watching the grunt's activity for any signs that an assumption is invalid. The importance of the navigator/commander role cannot be overstated.
Aside from poorly-named roles, much of the pair programming literature also places too much emphasis on role definitions. My hypothesis is that the real power of pair programming is two people working on the same problem but operating in complimentary mental modes. The exact responsibilities of each partner will shift throughout a session.
To Be Continued
I'll be pairing with a few people over the next month and will try to return with a follow-up about the experiment. If you've had an experience with pair programming, please share!