In the comments for my review of "The Art of Agile Development" an old colleague asked me a few questions about Pair-Programming, one of the key tenets of XP (which the book advocates). My response so was so long and detailed that I felt it deserved it's own post.
My current job is the first one where I've ever pair-programmed. I actually recall interviewing for it, and I was asked if I had pair-programmed before. I said sure, occasionally I would pull another developer over to my desk to help me and we'd sit together to figure it out. This apparently was a decent enough answer to the question that I got the job, but now that I've been pair-programming nearly full-time for five months, I've determined that what I was doing before was definitely not real pair-programming.
When I first heard I'd be pairing at the new job, I was a bit apprehensive and skeptical. Do I really have to sit next to some fat developer all day, 40 hours a week? When am I going to check my RSS feeds? What if the other developer is gassy or hasn't showered? How am I going to listen to my totally awesome Death Metal if I can't wear headphones? Will the other developer be constantly judging and correcting my code? Will pairing prevent me from hitting "the zone" where I'm just belting code out so fast that my fingers can't keep up with my brain?
Over the last five months, I've found answers to all of these questions: "no," "often," "that's rough," "easily," "sort of," and "YES, but that's a good thing."
The Mechanics Of Pairing
The way pair programming works in practice is quite a bit different than I imagined it. I envisioned a day where I couldn't escape the company of some other developer, constantly having eyes looking over my shoulder. I'm not a terribly social person, so the idea of interacting with a single human being all day was not my idea of a good time.
In reality, you don't sit down at a desk with another person and work all day with them. *You pair up for tasks. *
So, once all of the stories for the iteration have had concrete tasks assigned to them, people pair up to do them. So a dev and I might pick a specific task and work on it together. Two other devs pick another task. My pairing partner and I sit at a big 30 inch monitor and work on the task (just that task) together. Generally when you pair one person is the “driver” and one is the “navigator” so one person is implementing code and the other is thinking of design implications, refactoring opportunities, or the “next step” for the task. If you get stuck or pause or just want to switch, you pass the keyboard to the other person and switch roles.
When doing Test-Driven Development, one of the things we do is called “ping-pong pairing”. So the other developer will write a test, then make it compile but fail. Then he passes the keyboard to me. I implement the feature just enough to make the test pass, then I write another failing test and pass it back.
When the task is done and code is checked in, the pair breaks up. Generally tasks only have 2 hour estimates (sometimes less) so you’re only pairing for the two hours. Then you pair up with someone else to work on another task. If a task is taking longer than expected, or the pair “goes dark” (meaning they aren’t talking) then you shuffle the pairings.
Between these tasks, you might go have lunch, or take a break from coding to watch a video on youtube at your desk, or check your RSS reader for a few minutes, or go take a walk, or go downstairs and play some ping pong or foosball. We take breaks often because getting away from the code for a few minutes helps keep a fresh perspective when you come back to the task. Physical activities like walking or playing ping pong help with blood circulation, which helps your brain.
It’s also nice to have an odd number of developers, which we do. This way, one person is working without pairing. Usually this person will work on a defect instead of a story, or they’ll work on a story where everyone understands what needs to be done for that part of the code. If you don’t feel like pairing or you need a break, you volunteer to be the odd man out for a task. When I first started pairing, I frequently volunteered to be the odd man out and work alone. Today, having been pairing for a few months, generally I try my hardest to avoid being the odd man out.
In an 8 hour day, I’m probably pairing somewhere between 4 and 6 hours noncontiguously. It’s important to have a good setup for it - big monitors, comfortable chairs, no corner desks (so that the devs can be side by side at the flat desk with the monitor between them).
I see pairing work so well every day that I consider my career prior to my current job to have consisted mostly of wasting time. When I think back to all the code I’ve written for a job, I’m annoyed at how much less efficient I was then since I wasn’t pairing, and how much better my code and my products would have been if I had paired on them full time.
When you have a second person working with you, you find that you try harder to code well. You’re far, far less likely to be willing to apply duct tape to a problem, because someone else is working with you and he or she is more likely to object to the duct tape. If two people approve a hack and implement it, it’s almost certainly because it’s the right approach given the time constraints. If one person sitting alone decides to pursue a hack, it’s more likely to be a situation where there is a better approach.
Two people attacking a design problem together is easier than one person doing it. Your partner will think of things you don’t, and vice versa. In a non-pairing environment, you can always call someone to a whiteboard to help you work through a design issue, but when you do that you’re only calling for help when you know you need it. The times when you need help and don’t know it go unaddressed - and yet despite the fact that you need help, I guarantee that you’re coding SOMETHING and checking it in. It’s almost certain to be shitty code. The amount of time you spend trying to figure out “what’s going on here” or “why isn’t this working the way I expect” is severely reduced. I’m talking hours of debugging that literally turn into seconds.
Pairing also helps a great deal with collective code ownership. I don’t feel like there are any realms of the code that “belong” to any team member. You don’t have a situation where one person is the “expert” on a part of the codebase, since that person worked with someone else when they wrote it, and everyone likely shuffled around while it was developed. EVERYONE has seen that part of the codebase before, which means EVERYONE feels comfortable refactoring or extending it. This enables the team to perform improvements to any part of the code whenever they are working, which leads to technical debt being paid off very quickly. I often find myself shocked at how good the quality of the code is that we write and that we’ve written before. The product is ENORMOUS in code size, easily the biggest I’ve ever worked on, but there are very few areas of code that I would consider bad at all, and all of those are the earliest parts of the code that were written (and were written without pairing or TDD).
Pairing fosters a collective unity that I haven’t seen anywhere else. There are obviously issues and challenges, and there’s no denying that you’re producing fewer lines of code per day since only half your team is coding at any one point. I don’t consider that a bad thing, though (if you have two solutions that equally solve a problem, the solution with fewer lines of code is the superior one) because the QUALITY of the code that IS produced is so, so, so much higher.
There are definitely some challenges to pairing. Pairing at a corner desk absolutely does not work at all. The developers need to be side by side, the same distance from the monitor (which needs to be large). All instances in my career that I thought were "pair-programming" were not, because we were at corner desks. The person further away was, as a result, not as actively involved in the code (moving chairs is harder than moving a keyboard over a few inches). This isn't pairing, it's programming with someone watching over your shoulder. It feels like you're being watched, not like you're working with a peer. It sucks. I'm so glad that this is NOT what real Pair Programming turned out to be.
We have a team area with individual desks surrounding the area, but with "pairing stations" in the middle of the room. I find myself at my desk so infrequently (by choice) that my friends on IRC complain I never say anything on the channel. A good pairing environment is crucial.
Hygiene can be a serious problem. If one person smells, it's rough to sit with them. I find myself going back to my desk often and the code suffers for it. If you're pairing, take a shower, and hold your farts for your next bathroom trip. Just do it, you filthy pig.
The biggest challenge for me personally was essentially mourning for the death of "Programmer Man". Programmer Man is how I think of myself when I've got my headphones in, speed metal blaring in my ears, and I'm coding like a motherfucker. My fingers can't keep up with my brain. I'm In The Zone. For most of my career, this image is what I've considered to be the zenith. When I come home and was in Programmer Man Mode most of the day, I feel like I've had a good day.
Pair Programming undeniably killed Programmer Man. This was a tough adjustment, since I've considered that mode to be my favorite for so long. I now see, however, that Programmer Man was, without me knowing it, Technical Debt Man.
When you're coding like a motherfucker, you're often writing bad code. You're more likely to be outputting hundred-line methods. You're sometimes willing to skip writing tests (tests slow down Programmer Man). You're not pausing as much to think about design implications or ways that the code could be refactored. You may not have time to fix the code you're working WITH; Programmer Man is too busy working on his own code to give a crap about some other guy's code. Programmer Man's code is almost certain to be more brittle and more poorly designed than if someone were sitting with him, making him slow down and THINK more often. Programmer Man's code may not have been BAD, but it was generally worse than if he had a partner.
Programmer Man was too busy coding to do as much serious thinking, and the quality of the code suffered for it. And in the situations where you can be headphones-on, heads-down but still write tests and think about design, modularity, and quality, it's almost certain that two heads would have been better than one. If you're coding at a reasonable pace, pair programming will not slow you down. Conversely, if you code so quickly that pair programming slows you down a lot, you were making mistakes before. You need pairing more than anyone.
Programmer Man is dead, but I don't miss him. Not anymore. My standards for what is "good code" have greatly increased and quite frankly I'm not sure ANY of Programmer Man's code ever met that standard. Today, nearly all of my code does, and I have pairing to thank for it.
And the headphones situation is easy to solve as well - at work we pick a musical theme at the start of the day, then use Pandora to provide music consistent with that theme all day. I get my "Killswitch Engage" theme and my "Slayer" theme days because I graciously put up with another developer's "Angels and Airwaves" theme and "The Cranberries" theme.
When I leave my job (which I don’t see happening any time soon) if the next company doesn’t do pair programming, it’s going to be a tough adjustment to me. It would be like walking into a new company and finding out that nobody uses version control - everyone just copies their changes to a shared directory at the end of the day. Sure you get the job done, but god damn you’re being inefficient about it. When people hiss at pairing because they can’t listen to headphones or don’t want to sit next to a fat guy, it sounds to my ears EXACTLY like someone complaining about SVN being too complicated.
I'm not going to advocate pairing, because anyone who reads this post and says "hey, maybe we'll give it a shot" and then forces their team to do it will find that it doesn't work. For pairing to work, everyone has to WANT to pair. That means they all at least need to be curious enough about it to give it a genuine shot - attempting pairing with the attitude of illustrating it doesn't work will certainly show that it doesn't work. If you're holding onto Programmer Man, you're doomed.
But if you're willing to give it a genuine effort, push through the challenges and difficulties, read a book or two about how to pair, or maybe even hire a mentor to come to your company and help you pair for a few weeks, I think you'll be pleasantly surprised by how effective it is.