Practical Styles of Pair Programming
Without exception in all teams I've developed software in people have expressed their aversion against pair programming. It's not that developers don't want to try, or that they don't believe it will help. On the contrary, they are usually very enthusiastic about trying it and give it more than a fair chance. After a few days they sit alone behind their keyboard coding like zombies with headphones. What's going on? Is pair programming too hard? Doesn't it pay off? In this post I'll try to explain what I think is happening, and I will give you some clear pointers to avoid the traps. At the end I will go into distributed teams and what part of the game changes there.
So what are people saying when they have stopped pair programming and you ask them why:
- I'm faster on my own
- Can't pair with that guy, he's getting on my nerves
- Pair programming is too tiring
- We've split up the work and we'll get it done faster if we use two keyboards
- There's too much background noise
- I'm just slowing her down
Some of this might sound plausible, so let me axe that down first. No you're not faster on your own, you're just creating more crap for your colleagues to puzzle over and eventually delete. The code you write alone sucks. That guy that is getting on your nerves is trying to tell you (clumsily) that your code sucks, try to listen to him and you'll turn into a better programmer. Or maybe you can teach him something and he'll stop getting on your nerves. If your code is so simple that you can split up the work in advance you're writing it on too low an abstraction level, or you need to work on this in two pairs. If you're slowing the other guy down, that's a good thing. That will prevent him from writing code that you cannot maintain. If you don't feel worthy of your colleagues code, get over it, or get off the team.
That was your cold shower, I hope it woke you up, the rest of the post will be nicer. I've skipped a few complaints. I hear you, pair programming is hard! You will miss all those secret moments of rest where you glance over your email, look out the window, think of lunch... If the environment is distracting, being in a pair opens you up to this distraction more. If it is hard to communicate with your team members pair programming will make it painfully obvious. Somebody needs to fix that shit, yesterday!
Mute everything that is not relevant to the cause, including the client. If you tell the guy that is paying for your time that you can't work effectively when he's having phone calls with his wife in front of you he will stop, you're saving him a lot of money. Kill all the phones, just pull the plug, it's OK. There are plenty more tips, but the basic rule is: if it distracts you, make it go away. Then you're ready to go for some kick ass pairing.
To kick ass when pairing you need to know what you're doing, you need to know what makes things better and what makes pairing fail. I've noticed that there are four basic styles of pairing. I'll go over them and give pointers on how to go to a better style if you get stuck. In a pair there is one guy on the keyboard and one guy not using his hands. The first guy is called the driver, the second one is called the navigator. For some styles this is not a very descriptive naming, but when in doubt I'll use these terms. I'm investigating cases where the pair has the knowledge available to do the job properly which is not likely novice-novice pairing, although I feel the same patterns emerge when the pair is searching for knowledge along the way.
Style 1: The Commander and The Grunt, or The Backseat Driver
From the title this doesn't sound like a very pleasant way of pairing, but it is very useful to understand how it works. Some very positive long term effects can be attained by using this pattern against the odds so bear with me.
This style of pairing happens naturally when the driver is a junior, or he is new to the project, language, domain. In contrast the navigator is well informed and he'd probably be faster if he didn't have to wait for the driver to do what he is told. The grunt is clearly in the way of the commander. You can see the irritation rising as the commander gives more low level instructions like: "Extract field. NO don't type it, press Ctrl-Alt-F! No not there, select the method invocation first, no no no, you don't need to select every letter, did you use this IDE before? Give me the keyboard and I'll do it." Hilarity ensues when the commander finds that the grunt uses a different operating system and keyboard layout and his muscle memory doesn't work here. He moves to his own desk, puts on a headphone and is done with the task in 20 minutes. We should call this pattern the Jerk and the Moron and never talk about it again right? Wrong!
The trick is the muscle memory. There is a thin layer of good habits between the muscle memory and the stuff that the commander talks about when he explains what he has done. The grunt doesn't know this (yet) and he needs to learn. It would be wildly inefficient to get the commander to write it down and the grunt to learn it, so pairing in this style is actually a highly efficient way of transferring this type of implicit knowledge.
When I was in college my house mate had his own business and he needed to get something done. He also developed RSI and his doctor told him to leave the keyboard alone. He was in over his head and I offered to help out on the condition that he'd teach me Smalltalk. I didn't program a line of Smalltalk in my life and I hadn't even seen the IDE before. I was by all accounts a pretty crappy developer in general, but we were good friends and I just needed to press the keys I was told. How hard can it be we thought?
The first hour my friend went from explaining the domain and how Smalltalk worked through giving up, cursing through the pain, to yelling key combinations in my ear. Three hours later he was sipping espresso while I implemented a few builder methods. In the afternoon he went to the toilet while I finished a test case. At the end of the day he was drawing on a board and I was implementing what was there while he occasionally gave me instructions on how to name things differently, use the debugger instead of reading the code. It was quite pleasant and I had the feeling I could write Smalltalk code on my own. When I tried alone the next day I was completely lost, but I could do what my navigator wanted without annoying him after just one day of trying. The lesson here is that you can get someone productive in your team in a single day if you need to. You will have a tough day, but if you do this consciously and agree that it's worth it in advance the return on investment is pretty compelling. After a day you have slipped out of this style without noticing and things get better and better.
Style 2: The Rally
This is the style that preempted the driver and navigator metaphor. In a rally both the driver and the navigator have been where they are before, they know each other very well and they need only a small word to communicate. In a rally car you will hear things like: "Hard right. 3" "All out" "Left 6". If the navigator forgets an instruction the driver will just do the right thing anyway, and the navigator will continue with the next one. There is room for error, the chance of a crash is severely reduced by having the navigator there.
In programming people talk about "The Zone" or "The Flow" to describe a state of total concentration, or even a mild trance that is associated with high productivity. In rally style pairing the pair goes into the zone together. It becomes that much harder to disturb them because they are talking in a language that only they understand and they're ignoring everything but the code on the screen. The feeling I have with this state is very similar to playing certain games as a kid where a world would be made up by sharing a fantasy. The story would exist in the heads of several kids and very limited communication would be needed to keep the whole thing consistent. It actually helps to share the storyline with others, because then things that don't fit in (like a compiler error) can be filtered out with less disturbance.
Sometimes people have described that the navigator can prevent the driver to slip out of the flow, but in my experience breaking the link (which you'd have to do then) is rendering the navigator useless in a few seconds, so it's better to ignore the disturbance together. If you're on very familiar territory (like with the rally) this would work, but usually when developing software it's all about discovering new problems as you go along. If you're out of it, it is very hard to catch on. You might have guessed that this is the style of pairing that you should be after, so here are some tips to keep it going when you've found the right balance.
As a driver you should:
- Think out loud: "When I solve this with A now I won't have to refactor B before I can see if it works" "I'm running the test before fixing the properties file, we can do that later"
- Voice your expectations: "This test is going to pass now" "This should give me three invocations on this mock because I've simplified x"
- Ask the obvious: "What's next, ah yes we still need to fix that properties file" "Can we commit like this?"
- Give a heads up: "When we have done this we'll see some trouble in module A, we need to fix that too". And then trust your navigator to worry about it while you get there as fast as you can.
As a navigator you should:
- Follow the storyline and stop the driver if it doesn't make sense
- Actively confirm or reject assumptions
- Ask for arguments if a driver takes a non obvious solution: "Why are you doing that, if we change this property it already works, right?"
- Look for the nearest exit: "If you fix that test now we can do a commit first, the build will be green"
- Think ahead. If the driver gives you a heads up, he might not see a dead end. Think it through for a few seconds and then tell him if you don't think you're heading to a solution.
- Find a way out before you get blocked. This is the hardest one. Even if you're not sure you're running into a dead end it's good to keep an eye out for alternative routes to an exit. This will save time when you need to back out of something.
Style 3: The Tour
This style happens when a navigator looses focus and the driver is basically showing him around. Still you can switch back into rally style, but it requires a little effort on both sides. Make sure you're both on the top of your game, start touring and stick to the best behavior mentioned above and soon enough you should see that you're rallying again. If that doesn't happen within less than ten minutes, switch pairs (you can switch driver, which will start you off at Grunt-Commander style probably, if nothing works just try with another team member for a while).
Style 4: The Disconnected Pair or The Sleeping Navigator
This is the most used and least useful type of pairing. Two developers start off as discussing the design, walking through the code, and when the driver is on his way, the navigator shuts down his brain. The driver knows what he's doing and because the navigator doesn't pick up on what he's saying he turns silent and speeds up. The navigator sees that the driver is doing ok and decides not to slow him down but space out and look out the window a bit. When you do this in distributed teams you can catch up on your email while you're navigating, or listen to some music. Or do some coding of your own. If you're doing this however, you're not taking pair programming seriously and it's not going to do anything positive for you or your team.
Be selfconscious about this style when you're pair programming. When this has happened any change is a good one. As a driver you can suddenly revert all your changes and see if the navigator notices. As the navigator you can stand up and walk away to get a coffee. Just acknowledge that you have disconnected and something needs to change.
Those are the four main styles of pairing I've seen employed and I've tried all of them extensively, both in collocated and distributed teams. Before I will go into some things that are more important in distributed pairing I will get back to the point of pairing being tiring. Pairing is more tiring because you work harder. Way harder in my case in fact. The problem is that it is hard to remember that your brain needs a lot of stuff to do its job. In order of importance they are:
- a small break at least once every 45 minutes (every 20 minutes is better)
- water (most headaches are caused by dehydration)
- glucose (eat fat or proteins which are much more effective than raw sugar, but you need to eat them longer in advance)
- a good nights sleep
- caffeine (coffee really works and I hear it's healthy too 😉 )
The problem with pairing is that people (especially developers) like to pretend that they are machines and don't need to have a break. A good navigator will ask for a break after each commit and make sure there is a commit each half hour. If you're collocated you can even talk about how things are going, how far away from a commit you are etc at the coffee machine, where you also take a glass of water and a sandwich if you feel like it. You should also remember that most people can sustain hard brain work for at most 6 hours of the day, you can crank this up by doing sports and a healthy diet, but it's normal to be out of it after 8 hours. Just go home...
Distributed pairing is harder than collocated pairing, but it also has some advantages. The first rule of distributed pairing is to not get hung up on tools. The cool thing is that most of the hard parts of distributed pairing are technical problems and those can be fixed, whether you use GNU screen or some much more fancy tool, make sure you get the information to your pair buddy and he can see all that is relevant.
The first thing you should do is buy a headset. Don't be cheap about this, buy a good noise canceling microphone and something that you can wear comfortably. I'm a big fan of my Sennheiser headset, but there is a skype headset that is said to have better noise cancellation even. I'm not the expert on this one, but it is definitely worth spending some time and money on.
Spend a bit of time getting to know the other developer. Video conferencing really helps and I usually start my session sharing video and chatting a bit. It is easily forgotten how much more you can take from someone you just had a joke at the coffee machine with, but obviously you're not going to meet that developer on the other end of the world at the coffee machine. Be sure to ask about his schedule, lunch plans etc. If someone starts pairing with you just after your lunch and he hasn't eaten yet this is going to manifest at some point.
Be more zealous about small increments as switching driver is not that easy. I've tried many ways of giving someone control over your keyboard and they all suck, don't bother with that. The network latency is going to freak you out in 20 seconds. If you really can't commit in 30 minutes, it is easy enough to create a patch and send that over, but still it's going to take much more time than just shoving the keyboard over.
The good thing about distributed pairing is that once the tooling is set up you don't have to bother with the logistics of seat shuffling, straining your neck to see what the other guy has on the screen. You can just sit comfortably in your own chair and hear the other developer as if he was whispering in your ear, without breathing the pheromones of course. I'm kind of uncomfortable with other people in my personal space, and I'm not insensitive enough to miss the same apprehension in other developers. Remote pairing takes care of all that negative social overhead.
How pairing works is always different for different pairs. Labeling the pairing style might be helpful to talk about what is going on, it is never entirely possible to chose a pairing style and stick to it.
As an illustration I should tell you about my favorite navigator and my favorite driver. My favorite navigator is a quiet indian guy. When I pair with this guy I'm roughly 3 times more productive. The trick is I'm doing all that comes naturally, but he just doesn't let me go off in the wrong direction. It's like coding with a little muse on your shoulder. As you might have guessed this is Rally style pairing with me at the wheel. Then one day we switched driver. Things were horrible, I was constantly in the way telling him what keys to press how to name a field and things came to a grinding halt. My buddy told me that he didn't know what was going on but he was definitely much slower then when he was coding on his own. We switched back, music came on and we were on a roll that continued for the next 4 hours (with some breaks of course). Point is, you don't have to do it a certain way, just do it the way that works and try to figure out why it works so you can make it work even better.
My favorite driver is an outspoken dutch guy. He's quick on the wheel and if he doesn't get the idea I'm trying to convey to him he'll just type something to try if that works. When he does get what I'm mumbling it's on the screen faster than when I would have typed it myself, so it doesn't give me time to get frustrated over things not being like they would be when I had the keyboard. And that gives me time to look for exits and pittfalls. When I lectured him on changing his Eclipse defaults he not only fixed it exactly like I hoped, but he came up with a few handfuls of other changes and templates that are extremely useful. This is the perfect story about going from Style 1 to Style 2 nearing Style 3. Now when we pair I need to make sure I stay on top of things. Which is exactly the type of challenge that keeps a navigator productive.
In the end it's all about getting into Rally style pairing. If you find yourself in a backseat driver situation, try to turn it into a learning experience that transforms to Rally style. If you find yourself in a Tour, try to involve the navigator more into the storyline. When you're disconnected, stop and talk about it. Switching driver is usually helpful, but not if it takes you from Style 1 to Style 4. When in doubt, make the most experienced developer the navigator. But most importantly, try to make pairing a natural and enjoyable experience. Let me know how it goes!