One of the stated benefits of pair programming is that it functions like a continual code review -- ensuring that at least two sets of eyes see every line of code that ends up in the code base.
I spend a lot of time with people learning Agile approaches, and pairing is one practice that seems to invite a lot of misconceptions. One of these is that this code review aspect of pairing is the primary benefit -- and thus there is little benefit to pairing if you do formal code reviews (often these same people think that pairing is only beneficial when a senior and a junior work together). But not only is this not the only (or even necessarily the primary) benefit of pairing, but also the two practices provide different review results.
Recently, I was listening to a discussion where two different (but slowly merging) groups are trying to reconcile their disparate processes. One has incorporated several XP practices into their routine. The other is doing a more spiral-like methodology with very few Agile practices (although they recently started to try some). Because the goal of these groups is to build common terminology, and (ultimately) a compatible working environment, they (wisely IMO) have decided to allow both groups to continue with how they are comfortable, while adopting what they see as beneficial from the other group. So, the way things are shaking out, those that want to pair will pair, and those that want to do reviews will do reviews -- but management is not going to prescribe which is done.
One person even observed that someone may want to have a review session of code that was paired (which I found myself privately nodding along with -- I tend to be very open-minded about letting people do whatever they think adds value), then this person presented an example of why someone might want to do both. And this journal entry was born.
The example was: "Someone might want to do a code review of paired code to go deeper into things." I think this is a common misconception of formal code reviews. Code reviews, because of their presentation-like nature, the amount of code often involved, and the overall formality of the process rarely facilitate a deep understanding of the code. If this is your goal, pairing is a better way to go.
I am much more likely to understand your code, and see every design idea, coding standard decision, and implementation detail if we are actively working together in the creation of that code, than I if I get inundated with all of the your decisions in a two hour presentation of the finished product.
Thus pairing is deep -- it allows us to see all of the decisions made in the code.
Formal Code Reviews, are wide -- they allow more people to see what was done than those who did the work in the first place. This can add value (and why I tend to focus on what we want to accomplish rather than what we want to do), because there could be any number of people who did not work on the code, but will benefit from getting a direct look at what's going on (and code reviews often include more people than just a pair).
The point is, that its important to know what we are really trading off; rarely do we get something for nothing. In this case, we trade depth for breadth. This is why with both practices there are accompanying strategies to mitigate their weakness (e.g. change pairs frequently, do code reviews often) and techniques to maximize their effectiveness (e.g. driver focuses on syntax, pair on design; review a single class; define rules of engagement, etc).
The depth/ breadth tradeoff is not just in knowledge sharing, but in the actual resulting code (the benefit of both practices is said to be higher quality code). If I am the reviewer, my ideas are much more likely to actually make it into the code if I am there when its created, than if I make suggestions on "how it could have been done differently." In pairing I get to inform the creation, in the code review I only get to judge the creation -- my ideas will only make it into the rewrite (if it happens). In practice, this means that only the code deemed really in need of my ideas will actually include them, while if pairing, all of the code will (deeper). In trade, there may be many more people's ideas included in the rewrite (wider) after the review, while only those who paired the code inform its development.
So, which do you choose? The answer could be both, either, or none. What I hope to have illuminated here, is that this is not the most valuable question to ask. Instead ask yourself: "What problems are we trying to solve," and "What practices are we more likely to do." Because the people and the problems are always the important part. the practices you choose -- while not always equal -- are always effective in that context.