If you're working together with another person to write software, surely you don't need someone else to look over the code. That's part of the process. Or... is it?
Almost everyone I meet who practices pair programming says that they don't need other forms of code review.
They have a point: Pair programming is in some sense the "ultimate code review." It's continuous, so you're not just getting feedback at the end. It's deep, so subtle important problems are identified that might be hard to find in a later pass. It's personal, so people develop more rapport and a better working relationship with each other.
But is that the end of the story on code review? I'd argue no, in two ways: That certain important problems are missed in pair programming, and that we should all be open to applying different kinds of code review (including pairing) in different situations, rather than being absolute like "Pairing is always efficient."
To address the first point, consider briefly why peer review is so useful (and is required) in other disciplines such as writing. Every book author has an editor, and not because the author is unable to write. Rather, no matter how adept we are at the subject matter and the art of writing, we can't see the errors in our own work -- both at a detailed level (incorrect wording) and macro level (whether this reads well to a new reader, or what passages are difficult to parse).
The editor isn't there necessarily to instruct the author but rather to do what the author would herself do if the author weren't so close to the material. It's a matter of closeness, not ability. That's why everyone needs an editor.
Code reviews are the same. Of course, if someone else wrote that code and you were the reviewer you would have picked up on a lot of that too! Or if you were the domain expert you'd have the same insights. That makes sense, and that's why we all need code review.
Now back to pair programming. One of the (very few!) drawbacks about pair programming is that both people are involved in the creation. They're both "authors" in the sense that neither can assume the perspective of a developer who wasn't privy to this intense, deep process of creation and still needs to understand the code. That's something only an outsider can bring, by very definition.
You can argue how valuable that perspective is, or how much time it's worth to get that perspective after already incurring the cost of pair programming. I think the answer is: In some cases it's quite valuable, and in many it's not. You as the developer should use your judgment and be honest about when a particular change might be hard for a third developer to understand, and therefore it would be valuable to have someone else evaluate.
Also, it's different when you do a separate code review looking only for maintainability. Normally it takes lots of time because you're looking at correctness and scalability and compatibility and formatting and all sorts of things, but not in this case. If you're scanning only for comprehension, it can go really fast, like just 5 minutes for 100 lines of code. In that case, I'd argue the time trade-off is often valuable.
Speaking of the time all this takes, let's address the second point: the time-commitment for pair programming. Clearly the practice causes the immediate development to take twice as many staff-hours. The theory is that the quality of the code -- both in direct bugs and in architecture and documentation -- is improved so much that in the long view we actually spend less time to deliver solid, working, maintainable code.
I won't argue that other forms of code review are as intense or as deep, but it's obvious that other forms take less time up-front. (In our studies at SmartBear, users of our software Code Collaborator spend about 1/8th of the time in code review than in writing the code.) And it's clear that these other forms will certainly confer some of the benefits of pair programming, such as finding bugs, making code more maintainable, spreading knowledge, and working together. Just not as much as pair programming.
Suppose the benefit is 36% as good as pairing but 12% of the time commitment. That's a 3x more efficient use of your time.
Clearly sometimes the code warrants pairing. For example, when the problem at hand is really difficult, or when one of the pair is a domain expert at the problem, or when you're training someone. But often the change is simple and a quick look-see is sufficient. Or most of the change is in your area of expertise and you need a domain expert to peek at just one file.
Clearly in those areas it's probably more efficient to use another form of code review.
Maybe now we can all stop being so dogmatic about pair programming as the be-all-end-all, or that pair programming always takes too much time, and just agree to be sensible about how and when it's useful, and what advantages and disadvantages it presents.