I’m curious to hear from people about their experiences pair programming. I’ve been pairing full time for the last few months and it’s been a super interesting way to work.
I haven’t been able to find much about peoples experiences' over the long term. I thought that was funny given that some big development shops are so sold on its effectiveness.
I can’t stand pair programming, and I simply would not work somewhere that required it.
I’ve tried it a few times, and have had only bad experiences.
People either point out stupid errors that the compiler can catch, or they question every little thing you type, or they throw out a million suggestions before even seeing what you’re doing.
Besides that, it just doesn’t work with my coding style. I’m always going back and refactoring the code I just wrote a minute ago. Very rarely am I satisfied with code the first time through. I don’t need somebody sitting there criticizing it - I probably already know I should have commented that line or ripped that expression out to a variable, or made that a while loop instead, or whatever - I’ll get to it in a second but thanks for making me lose my train of thought.
Code reviews are a far better use of everybody’s time, IMO.
Clippy: “Did you mean…”
A thousand times yes! Well said.
I never did new development that way. But for debugging it was kind of fun. I’m not sure we were 2x effective, but 1.5x effective at finding a critical bug can make a big difference.
Watching somebody type is like a kind of mental torture. But clicking around a debugger, reviewing log output, etc. never triggered the same twitches.
Agree on debugging. I have participated in some code walkthroughs (both led and been led) with others when trying to track down some very goofy logic bugs in very dense code. Super useful there. As @vadik mentioned earlier, also a very big fan of code reviews.
Pair programming though? Super not a fan.
This is interesting. And it’s funny that nobody else mentioned debugging, although it’s probably more common than writing new code.
But a big part of debugging (and understanding how to implement new features, for that matter) is reading code. And when I read code, I tend to jump all over the codebase tracing fuction calls (both ways) and variable assignments (thanks cscope, life was terrible without you), and following such activity closely at normal speed is impossible. When I help someone debug, I often find myself saying things like “slow down a bit”, “can you scroll up?” and “what exactly are we looking at?”. And there’s the issue of concentration: once you ask me a question, three facts about the code will fall out from my short term memory. Though when help is needed, I agree with you, debugging together is not so bad.
But I would regard such coöperation not as debugging/designing with the aid of another human, but as talking about the issues with the aid of debugger and editor. Because at this point person A has done some work and understood some things, and now (s)he’s showing it to person B and asking for input, so naturally it should flow at the pace of conversation. Doing it all the time, however, is madness.
I’m personally strongly against it. Programming, as in the act of writing code, is a solitary activity. I find it impossible to concentrate with someone sitting on my shoulder, so pair programming not only wastes the partner’s time, but the programmer’s time as well (whatever is the official terminology for the two parties). It seems to me like yet another aspect of the insane modern management fad of “coöperation”. If I need help, I’ll ask a colleague and we’ll coöperate nicely; otherwise, just let me work.
I did, however, push for mandatory code reviews at my current workplace. It gives you all the benefits of having more pairs of eyes on the code (and, from experience, it’s one of the best ways to catch bugs), but without wasting so much time.
Heh. I am reminded of advice I once heard from a teacher to a student engaged in memorizing arithmetic tables. “You don’t need to help each other. There’s no helping in arithmetic. It’s between you and the numbers.”
I do think this is a valid perspective, and really does apply to many programming tasks. When a piece of code is very-high-risk and not possible to fully test before deploying it, there can be exceptions, but those scenarios are extremely rare.
I very much second mandatory code review. For catching mistakes, if the review is treated as meaningful and not just as a rubber stamp, it’s far better than pairing - it’s a lot easier to unconsciously give your pair your same biases when you’re face to face. Besides, I enjoy the sense that somebody has looked at my work. :)
And you can avoid the inevitable (but hopefully rare) 2x the time wasted looking for a bug. Although it cuts both ways as you might find a bug twice as quickly.
When a piece of code is sensitive or non-trivial, it and its design surely must be reviewed carefully by people who know what they’re doing. Though I still wouldn’t go the pair programming way. In fact, one of the features I’m implementing these weeks was preceded by month-long e-mail threads, some meetings, input from lots of people (not all of them technical) and a funny equasion-filled document summarizing it all, but no pairing at any point.
Interesting point about biases. And yes, if code reviews aren’t meaningful the whole point is lost. But my enjoyment comes more from the sense that somebody didn’t let me commit crap code to the repository, regardless of the frustrating aspects of it all (“oh no, not that thing again – alright, ok, thanks for not letting me be a pig”).
[Comment removed by author]
Great article, it raises some good and bad points of pair programming that I hadn’t thought of.
I would disagree with this quote. When I code or debug, especially when it’s something big or non-trivial, I often try different approaches, have dirty code with /* XXX */ all over, sprinkle it with debug messsages, copy and paste, work on different parts of code in chaotic order (e.g., when designing a new API) and sometimes accidentally commit some of this mess, so someone standing over my shoulder would just create pressure. Before code review, when everything is ready, I clean the code and “git rebase -i” commits in a logical easily reviewable order, and that’s where the motivation comes into play.
The use of the word “everybody” obviously doesn’t apply. In its place I propose: “I’ve found that most people are more disciplined when pairing or in a group, especially with someone they respect”.
On a separate note, what if, after all that work, a code reviewer pointed out a much simpler way to do what you did, that would have taken 1/10th the time?
It kind of does, methinks; it’s just that, for some, the negative effects of a peer’s constant presence offsets the positive ones. More disciplined plus more tense equals different things for different people, I guess.
This would mean wasted time, of course. But I would argue that, commulatively, it would probably waste less time than constant pairing. Besides, this argument goes both ways — what if, after pairing and reviewing and debugging deploying, half a year later, another programmer sees the code and points out a simpler way to do it?
Also, as I said elsewhere, if you’re writing a big or non-trivial piece of code, you should probably talk to someone about the design. Seems to work for us.
I’ve paired full time, by which I mean about 4–6 hours a day, for a couple of years. It was very productive, especially by helping to suppress distractions, but also pretty stressful. It helps a lot with team communication. It does damage some kinds of creativity, and it can be frustrating (but maybe at its most productive) when you’re pairing with someone without the same background.
I think the right balance is:
And it’s not ideal for every situation. There’s probably production code that doesn’t benefit from pairing, and people who don’t benefit from it. I do.
Yes, my boss and I do pair programming via his obsessive compulsive micro management over email, skype and automated code reviews. It’s like he’s sitting right there beside me :)
I’m for pair programming though I’ve never done it full-time. I think it’s a valuable tool for passing knowledge around a team, and helping to bring up the level of more junior developers. One of my main priorities is helping to bring up the level of my teammates and I find pairing to be a very good way to do that. Code review is also very helpful for this, especially if everyone on the team participates in the reviews. I just see it as another tool in the toolbox, sometimes it’s useful and sometimes there’s a better tool for the job.
The times when I have paired with a more experienced dev, I’ve found it incredibly valuable as well to get a different perspective on the how of development – tools, shortcuts, train of thought, etc. I’ve learned many new things in vim from pair programming with people of greater experience than myself.
On the other side, I do find pair programming mentally draining, because I find that I’m less likely to get distracted while I’m pair programming than while I’m programming alone. It’s easy to take a micro break when you are programming alone, but less easy to do when you’re working on a problem with someone.
I’d never force someone to do it, but I do encourage it amongst my teammates.
Training and passing knowledge are certainly good points. Though I likewise find pairing emotionally draining (and hate it with passion for all the reasons @jlarocco enumerated), so I’d tend to replace pairing with commit sessions (like code reviews but you stare together at one screen), smaller tasks for inexperienced people and, most importantly, asking for help when needed. And, for non-trivial tasks, talk to others about the design. (I’m trying to encourage such attitudes at work and it seems to work fine, not that I’m a team leader or anything.)
I do pair, or mob, problem solving but program alone. The act of writing code is purely mechanical.
I think it works as in produces better code. I don’t enjoy it. I’ve done it full time at a previous job.
My experience is that it leads to lowest-common-denominator code. If you’re pairing a couple junior folks that might otherwise be slacking off, I guess it’s okay.
As in average/bad code or as in simple code? I think simple code can be an advantage, “Why are you doing it that complicated way? Just do this…”. Of course much of this tidying up can talked about in an automated code review. And at least then you get the benefit of the earlier revision being in version control before refactoring.
Yeah, I’ve very often had my pair say, “Why are you doing it that complicated way? Couldn’t you do it this more straightforward way instead?” and usually they’re right. And I get a lot of benefit from them telling me not to write that tricky code that’s going to take me three hours to be sure it’s right before those three hours are already over.
Or you might just be fanning the flames for a session of office chair hockey!
My team is geographically distributed, so code review is the only model that will work. As long as you keep review latency down it works pretty well.
I have had some really bad experiences pairing, and some really good ones. It’s great for communicating, as others noted. Most of my experience was early in my career, being the bewildered junior of the pair, and I learnt a lot that way. It was very draining though! For that reason we rarely paired a full day.
You do have to adapt your style of work when pairing. Instead of just thinking about a problem, talk about it.
I am confident that pairing we ended up with better code than either of us could do on our own in the same time. Was it 2x better? Perhaps not. But with the time saving vs code + review + address review concerns + new review… I’m pretty sure we came out in favour of pairing.
Slow round trips for reviews can certainly be an issue, but where I work it’s solved by taking one’s eyes off the screen and saying, “hey $COLLEAGUE, what about that merge request?”. And there are also commit sessions, in which a committer sits with the author and the latter has to justify every line of the commit. One former workplace had both commit sessions (before the code goes into master) and code reviews (after, so non-blocking), but for that you need a big pool of programmers.
I’ve had very good experiences pairing with someone much more experienced than me: I found it a very effective teaching / mentoring technique. (I also believe the senior got something out of it: having to discuss things with me as well as with the compiler did sometimes give them insights they probably would have missed if working alone.)
We pair on 90%+ of production code - as a rule of thumb we try not to push anything live if it’s not been paired on.
It’s not just about having “real-time code review” although that is a bonus - we use it as a tool for knowledge transfer. The ideal situation would be the entire team having a thorough understanding of the whole stack from front-to-back, and we find that pairing is a way to facilitate that.
In addition, I feel it’s a good technique for simultaneously picking up better practices and having fresh eyes to ask questions - if you can’t explain why you’re doing something, you probably don’t have a good understanding of it? (As a generalisation).
That’s not to say everyone is forced to pair all the time, that wouldn’t make sense. Pairing isn’t nearly as useful if you want to spike something dirty as a proof of concept, I wouldn’t even write tests in situations like this. I believe it is useful in writing production code.
tl;dr - pairing’s benefits are increased code quality in addition to being a good learning tool, a way to spread domain/tech knowledge within a team, and it’s a social activity as a cherry on top.
Some don’t like pairing. I do, and I think it’s effective for me.
But why are code reviews not adequate for knowledge transfer? This was, in fact, one of the reasons I pushed for code reviews at work. The only issue I can see is with big self-contained pieces of code, which tend to reach the review in one chunk. It is an issue, and it’s not too easy to work around. (Design reveiews solve some of that, but seriously, who designs before coding?)
Explanation is a valid point, but if the code doesn’t speak for itself, it should be followed by “and now you’ve explained it to me, write a comment / rewrite the code simpler”. And, again, it should (and does) work in code review context as well.
…but but but, production code is proof of concept code merged in a hurry ;)
I think there’s a difference in understanding by doing (pairing) and by reading (code review). The code being written does not consist the whole of the functionality being deployed - data changes, for example.
How many people have to review code where you are? (Honestly curious)
It strikes me that if there’s no constraint on it then you would probably end up developing points of failure, which we try and counter with active pair rotation. Each person should have worked on a single feature or have knowledge of how it works for supporting the code in production, which I don’t see how can be effectively achieved in a code-review situation.
If anything, I think pairing is occasionally not effective enough for our constraints - I much prefer Mob Programming, which we do and has been getting a bit of attention recently. (tl;dr it’s pairing but with the entire team). The advantages are that it reduces the time for everyone to understand the code, which is absolutely critical in things like code that affects finance/security and moves things much closer to One-Piece Flow - which is the way we like to operate.
In our scenario all the data we have is in repos and undergoes code review as well.
Everybody on our team has to review code. (One reviewer per merge.)
If the code reviewer understands the code (s)he reviews, then knowledge transfer is done (though, granted, not as effectively). And if people are given tasks to do in various areas of the code, they get familiar with the codebase at large. But there’s a balance between this and “code ownership”: there are arguments for a small number of people (one?) having more impact on architecture and overall direction of the project, and the right point is not easy to hit. We may err on the side of code ownership, but I believe that if any of us gets hit by a bus, the others will be able to pick up the pieces quite quickly, although of course there will be impact.
A former workplace with many programmers tended to err on the side of knowledge transfer. There was some specialization, but by and large everyone worked of everything. And, although they had around three architects, the codebase did exhibit the too many cooks syndrome, and its quality varied.
It’s late in my timezone, so I’ll look at the links tomorrow. I should, however, say that I’m somewhat wary of all these new shiny processes promising the world. In my opinion, nothing is better than careful engineering, which requires time and quiet.