Thoughts on Pair Programming
Shahar Kedar
Posted on March 24, 2024
I am currently leading a team of four very talented engineers, and we started practicing pair programming more often in the past few months. To be completely honest, my initial motives for pairing was mostly personal growth. I was happy to see though that not only was my team happier, but they were also more productive. I've known and practiced pair programming a lot in the past, but only recently have I given it some more serious thought.
A lot has been written over the years about pair programming. I'm not even sure if this is still a "thing" or a long-forgotten practice (if you're practicing this regularly, do tell!). But since people keep writing about it, I'll assume it's live and kicking. Unfortunately, the general vibe is that some people need to convince other people that pair programming is productive.
Honestly, I don't want to be part of the conversation. If you're not convinced that there's some merit to pair programming, you're welcome to stop reading now. I'm here to preach to the choir - because honestly it's more fun - and talk about something else: when does it make sense to pair with someone?
Certainty
As engineers we need to deal a lot with (un)certainty. Sometimes our job is to take a well defined task and implement it in a well defined architecture - high level of certainty. I would argue that in those cases we want to optimize for execution time. The quicker it gets into production and into the hands of customers the better.
In other cases, we receive a task with a lot of uncertainty. Either the task is not well-defined technically or from a product perspective, the architecture does not exist or doesn't fit, or there are other risks we identify early on. In my opinion, in those cases we want to optimize for clarity.
"Wait what? Why not also execution time?" you might ask. You wouldn't be wrong. As a business, especially as a startup, we always want to deliver as fast as possible. BUT there's also a price for running too fast especially with high degree of uncertainty. We might deliver the wrong thing, deliver a buggy or a poorly performant feature. We might, god forbid, have to write it all over again. And that affects execution time in a very sneaky way that's hard to identify and mitigate.
So... creating clarity. I think that should be our number one priority. Turn uncertainty into certainty as fast as possible so we can get back to optimizing execution time.
Pair programming in high certainty tasks
There are two cases, in my opinion, when pairing in high-certainty tasks makes sense:
The engineer who owns the task is not proficient enough - this usually happens with junior developers. Even though the task is well defined and poses little risk, there's a chance that a junior engineer will still not do it fast enough. Since we're optimizing for execution time, we need to find a solution. IMHO pair programming is an amazing solution for that. Not only it reduces deliver time, it also increases the junior developer's mastery - 2 at the price of 1.
The engineer who owns the task is proficient but not familiar with the code base - in this case pair programming has a simple goal: reduce ramp up time. Depending on the case, we could restrict the pairing to last only until the owner "gets it" and can continue solo.
Pair programming in low certainty tasks
Here the level of proficiency or knowledge plays a significantly smaller role. It is my belief that it's always worth pairing on low certainty tasks. Pairing serves different purposes:
- Quickly identifying blindspots - many engineers tend to simply start writing code as a way of thinking about their task. I know I do that a lot. This often creates a "tunnel vision" where we think more about the code we're writing then the task we were given. Having another brain that's not occupied with writing code, really helps surface blindspots early on.
- Fast feedback loop - one of the biggest advantages of pair programming in general is that we have a partner with whom we can bounce ideas around and zero in on the right solution quickly. With low certainty tasks we need that level of feedback and creativity, because we're almost sure to reach obstacles a lot. When there's no dedicated person to work with, we often spend a lot of idle time waiting for someone to become available.
- Psychological commitment - sometimes when we're faced with a really difficult task, we tend to wander to other tasks on our plate that are easier (or death-scrolling on social media apps). This behaviour creates a lot of context switching and lengthens delivery times. When pairing we are committed to working on the task at hand. We have little chance to lose our focus. We also have the ability to switch roles if we become tired.
All of the above can significantly reduce delivery time while increasing quality. Theocratically, we could have done two different tasks in parallel - but the result would have been poorer and not necessarily faster.
What now?
Now I need to start practicing what I preach. I'm going to try and intentionally use the "certainty" criteria to decide if pair programming is necessary. I'm also going to try and find other criteria that I can apply consistently. I would love to hear your thoughts - what criteria do you use?
Posted on March 24, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.