Whenever I describe the agile practice of pair programming I usually get the same general reaction,which is something like “I don’t think I’d like to do that”. My usual attempt to convince someone that it could be an interesting tool to try is to suggest that verification team could do it for the complicated sections of code, or to have the designer and verification pair program to develop the drivers. While good reasons, these were never enough. This posting will be another attempt on my part to show the value of pair programming, and to provide some suggestions on where programming could be effective for you, and some reasons on why pair programming may not be effective.
First, I need to step back a bit and explain what pair programming is. Simply put, pair programming is when two engineers sit down together to design and implement a piece of code. One engineer is responsible for driving (i.e., they own the keyboard) and they are the ones that physically write the code; while the second is responsible for providing support through discussing the code as it’s being written, constructively pointing out problems, updating diagrams, looking at the other supporting or interacting classes for issues, researching solutions on the net, etc. — basically providing support and instantaneous review of what the first engineer is typing. The engineers can and should reverse the roles on a regular basis, or when the “support” engineer wants to show what they’re thinking by asking for the keyboard and putting down their ideas. Now honestly evaluate whether your first reaction to pair programming was “I don’t think I’d like to do that”. Hopefully, the rest of this posting will convince you to consider trying it.
The advantages of doing pair programming are the following:
- higher quality code: following the adage “two heads are better than one” — the code is being continuously code reviewed as it is written. The likelihood of silly “finger” troubles are less likely. As well, having someone able to sit back and take a look at the bigger picture while the code is being implemented can possibly allow the interaction errors with other supporting modules less likely. A corollary to this is that you’ll also have likely higher quality code comments — your code buddy will make suggestions for a comment that will be meaningful to more than just one person.
- team building: sharing the responsibility of design and creating something is definitely a team morale booster. It fosters confidence in the other person’s skills, and allows you to share your knowledge with someone else — making your team stronger in the process.
- common ownership of the code: ideally, everyone is responsible for the entire code base. However, what can happen is that egos get in the way and people feel that they own the code, and that no one should really be touching it without their permission. While this is not eliminated using pair programming, it can be lessened.
All good valid reasons that many folks can accept. However, to ask them to actually try it… that’s when the roadblocks are put up. Most people I work with are senior engineers who feel that that is not the best way that they develop their code, and think it will be too slow or inefficient to have two people working on the same code at the same time. The interesting factoid that I’ve noticed is that many of us do pair programming in short bursts — usually when there is a crisis, or when we’re not making progress in our design process. Our first reaction is to discuss and review the issue with another person. Whenever something breaks in the code and it’s either impacting others, or there’s time pressure, we generally grab one or two people to go to the nearest whiteboard and discuss, or get one or two people to come over and look at the code that seems to be problematic. We’ve all done it. Why? Because it’s the usually the fastest way to resolve an issue. It usually helps to describe the problem to someone else, show them what you’ve tried to resolve the program, and then ask them for their suggestions on what to do next. I have done this many, many times over my career, and I think most of of us have at one point or another.
Now my question is: if the most efficient way during a crisis is to ask a colleague for a review and provide suggestions, why is it not that efficient to do when there is no crisis and while the code is being written? In essence, pair programming follows the same principles as what happens during this crisis.
My second point on this “pair programming is inefficient” argument is that ASIC/FPGA development is similar to software in that we spend a LOT more time supporting a line of code than we actually spend writing it. That is, we spend more time analyzing, designing, documenting, reviewing, refactoring and, most importantly, debugging a piece of code than we do actually writing it. Having two people working on the same original code at the same time is simply not going to impact our productivity negatively. In fact, I’d argue, and there is anecdotal and empirical evidence to support me, that pair programming actually reduces our time to complete a piece of code [Williams] [See Wikipedia entry “Pair Programming”, section Scientific Studies”]. As with asking a buddy to help during a crisis is more efficient, asking them to help when there is no crisis is just as efficient.
However, for full disclosure there are dissenting views and studies on Pair Programming. The one I found interesting was a meta-study of all the other studies [Hannay]) that indicates there is only minimum effect on quality, and it takes longer, and requires more effort. These studies (with links below) are an easy, excellent read and I encourage you to review them so that you can make up your own mind on whether pair programming is worth a shot for you and your team.
Potential Pair Programming Problems
While I believe that pair programming has worth in many, if not all development chores, I realize that it won’t work in every situation. However, the reasons pair programming may not work are not due to the technique, but rather the people-related issues. The experiences and attitude that come with pair programming will affect both the value that is put into the effort, and the results and impressions that come out of it. Chiefly, this comes down to ego and personalities. People do get invested in the designs that they create — that’s a good thing. But for some folks, there is a limit on whether they can accept ideas from others around that design — that’s not a good thing. Or that the task is so straightforward or of medium complexity that it is really is a “waste” of time to have two people do the same job. My only counter-point is that all code has to work for the system to be reliable, tiny errors accumulate to reduce the overall quality. Similar to code reviews (but pair programming provides a much more active role for everyone), pair programming helps ensure that every line of code is of the highest quality possible.
In terms of experiences that each partner brings to the effort, there are three very coarse combinations of “skills” partners:
Please note, the use of the word novice is not intended to mean someone fresh out of school, it could mean someone who is new to your company that needs to learn the ropes.
I’ll review those one at a time and discuss where value can be extracted from each of these combinations:
- novice-advanced: If the goal is to mentor the novice, then pair programming would be an excellent way to help with the mentoring. It would allow the novice to ramp up quickly and ask questions; allow the advanced user to explain historical, significant reasons for getting to where they are, as well as offer the novice an opportunity to ask questions and offer suggestions on how it could be improved.
- advanced-advanced: As above, this pairing would only work if the personalities involved were willing to give it a try. Ideally, this pairing will work on a task that is particularly complex, or some important piece of IP that will be reused many times in the current project or potentially across many project. In general, one key value of pairing is to facilitate discussion, so using pairing for any job would be valuable simply for that benefit.
- novice-novice: While this pairing would require support from the more advanced user (or where the documentation is excellent), this is another way where two heads are better than one. The novices could help each other learn more quickly by discussing the problem, potentially bringing their previous expereinces into the solution, and then coming to a consensus approach or involving an advanced designer in the formation of the solution.
The other aspect of pair programming that could make it a demotivator is if the two people don’t normally work together effectively, pair programming will likely be disastrous and ineffective. Care should also be taken when pairing a novice-advanced combination in a mentoring situation — watch to see how they play together. It would be nice to say that as a professional, everyone can rise above this — especially as your corporation is paying you to work with everyone else — but the reality is unfortunately very different. Wishing it were different is not realistic.
Good Places to Try Pair Program
Here are some areas where pair programming is especially effective (assuming that I’ve convinced you to give a try):
- Important or Complex Verification Classes: Where many people need to understand what the class is supposed to do e.g., an important or complex base class. Where the the design of API/usage model must correct, or where the algorithms implemented are complex.
- Functional Coverage Model: Verification and Design working together to design and implement the functional coverage model. Creating the coverage points ensures an understanding of what kind of stimulus will be required. This will likely be an incremental work i.e., created in short spurts as the environment is developed.
- Interface Boundaries: Either between two designers or two verification people. Creating the functional interface or verification drivers increases the likelihood of the two interfaces working together and creating a common understanding of its functionality.
- Assertion Development: Related to interface boundaries above, having two designers or a designer/verification pair create assertions around an internal interface protocol, or complex state machine would be beneficial. Pair programming helps with the both the definition and optimization of the assertion.
In conclusion, I think pair programming has a lot of merit to use regularly. I think it’s another tool to help us create higher quality code and be more productive in the long run. I believe that Pair Programming and Test Driven Development (a topic that Neil and I are currently preparing a set of blog posts about) are the two low-hanging fruits that are easy to adopt — assuming you’re willing to give them a try. I challenge you to find a willing partner and give pair programming a try. I’d welcome feedback on both where it worked well, and where it didn’t work as well.
- [Williams] “Strengthening the Case for Pair Programming”, Williams et al, 2000 (http://citeseerx.ist.psu.edu/viewdoc/download?oi=10.1.1.33.5248&rep=rep1&type=pdf)
- [Hannay] “The effectiveness of pair programming: A meta-analysis”, Hannay et al, February 2009 (http://www.sciencedirect.com/science/article/pii/S0950584909000123)