First, I want to say that I think pair programming is fine - for other people. Based on pairing fulltime for a month at Pivotal Labs, I've been exposed to both its good side and its bad side.
First, the good side. I think the production of good code with two people working together is greater than with two people working apart. It's not hugely greater. The pair has to generate twice as much code as one programmer just to break even. That's helped by the fact that pairing forces you to spend the day programming instead of goofing off.
But where pairing wins is the "good code" part. From my experience, stupid little bugs (which accounts for the great majority of bugs) are caught much more frequently at coding time. That's a big win.
I also think that there is way less "bad code" produced. "Bad code" can happen when someone makes the wrong design choice and spends time going down a rathole patching and fixing the code.
Those are the good parts of pair programming. I've no doubt left out others. Now for the bad parts.
When you pair program, you're effectively joined at the hip with your pair. You can't pair if only one of you is there. This means that you both come into work at the same time, you both take lunch at the same time, you both take breaks at the same time, and you both leave at the same time. The work is so concentrated that you work 8-hour days (which is good). But you can't take time off without affecting your pair. Working from home is possible, but it's obviously not as pairy as sitting beside one another. This is an aspect of pair programming I hadn't considered until I tried it.
You have to be able to think out loud - 8 hours a day. Then you have to type in code while someone is watching you. They'll catch your typos (hopefully after giving you a chance to spot them yourself) and they'll see when you're floundering for how to do something. This turned out to be my own personal biggest problem with pair programming. When I was at the keyboard, I got dumber. It could be simple nervousness, or it could be that gaps were being exposed in my knowledge - gaps I felt shouldn't exist. Either way, I was not comfortable, and I was definitely less productive than if I were on my own. This is a personal reaction. I don't consider it a failing of pair programming, but a failing of me.
I may have been able to work through this handicap. I certainly learned more in one day than in a whole week of solo programming. And there might have come a time when I was comfortable programming in front of other people. But there was an even bigger problem.
Pair programming doesn't encourage quiet reflection and exploration. You can't just sit back and read some code. You can't just sit and think. I mean, you can, but then your pair is just sitting there. If you both agree that such contemplation is necessary, that's fine, but what if your pair is perfectly happy with an existing way? You don't want to waste their time. You don't want to argue (unless the other person wants to as well). You give in more often than if you were working alone.
This can be a good thing. When each of you have veto power, that reduces the chance of bad design. However, I think it also reduces the chance of truly innovative design (unless you both agree to explore it).
An example might help. We needed to display a graph of the relationship between entities. The models contained the names of the entities and the names of their relationships. The graphing "little language" needed to be generated for each entity and relationship. My pair's idea was to give each model a method to generate the graphing code. I felt that graphing code was for viewing the models - not part of the models themselves. I proposed a Presenter to translate models into views. This certainly sounds more complicated than putting the code in the models, which is what what my pair wanted to do, and so that's what we did.
The design was perfectly workable, but it lead to its own complications as the work progressed. For example, when you click on a node, that node becomes selected. In order for the model to create the graphing code for it, it has to know which node is selected. This meant adding a 'selected_node' parameter to each call to the model graphing code. That wouldn't have been necessary using a Presenter who was in charge of graphing the model tree.
There were other small problems, and I believe more problems would be found as we worked with the code. The reason is because we were violating MVC.
I made this point to my pair (who was an extremely intelligent guy), but he disagreed, so we did without a Presenter. Big deal, right? But when you multiply that scenario by ten or twenty, you'll get some idea of my experience working with pair programming.
TDD? Well, we do it when it's easy. It's not worth testing views, after all. And what difference does it make whether you test before or after you write the code, anyway? Database normalization makes things too slow. MVC requires writing additional classes. Cucumber is only valuable when clients write features. Fixtures are faster than factories and mocking.
These were the sorts of issues that came up during my one month of pairing. And I lost on every point. That, to me, is the greatest drawback to pair programming (at least when I'm doing it). You just want to get the story done. Innovation can be stifled. Programming according to generally recognized principles is cast aside, as long as one of the pairs (especially the dominant one) "doesn't see the need" for it.
And that's the kind of stuff I'm good at. I reckon that 95% of my code over the last 10 years has been written in response to a failing test. I keep view code out of models (and vice versa). I program from the UI in, because I think what happens on the screen and the keyboard is the only truly important part of an application (everything else is implementation details). My database tables are in third normal form. I believe I write well-factored code that is simple because it puts responsibility in the right place. Of course, I know there are exceptions to every one of the preceding principles. But you start by doing it "right."
So that's why I don't like pair programming. My weaknesses are exaggerated and my strengths are vetoed. For me, pairing doesn't work. For plenty of others, it very clearly does work. But not me. And that's why I quit the best company I've ever worked for: Pivotal Labs.
