What most effective teams have in common is certainly their ability to work together. When it comes to software development, one way to work together is pair programming.
Pair programming is a technique where two developers sit at the same desk and code together. The purpose is to spread knowledge over the team, share good practices and sometimes overcome technical challenges by combining two people experiences to solve a problem. At any time, one developer is coding while the other one reviews each line as they are typed and thinks ahead. They must engage with the task to perform for this exercice to be beneficial. Thus, no place for procrastination.
From the point of view of a manager, two developers working on a single task may appear like a waste of resources. However, studies have shown that for a 15% longer development time, pair programming improves code quality, reduces massive show-stopper bugs and enhances team communications (see “The Costs And Benefits of Pair Programming”: https://collaboration.csc.ncsu.edu/laurie/Papers/XPSardinia.PDF).
Let’s see when to pair and how to do it effectively.
Even though the ultimate goal is to produce a fully working piece of code, pair programming can be employed for various reasons. Generally, it depends on the skill level of the participants.
The most common usage is a junior programmer pairing with a senior one. The former types while the latter instructs on what to do or help the junior figure it out without giving the solution beforehand. In this case, pair programming is used as a learning and on-boarding tool.
Roles are not exchanged at first. Junior programmers can’t learn by only watching someone else type lines of code they might not even understand. Either because they don’t know the code base yet or because they’re lacking experience. They have to experiment a bit their ideas and make their own mistakes to learn.
Thus, senior devs have to resist the urge to always take over the keyboard control and even show any sign of irritation. Patience is the key here. Sure you would have done the task in a minute, but would that serve any purpose? You don’t want juniors to be discouraged and leave the team. Instead, senior devs should progressively bring juniors to the path that lead to success.
To make this happen, the junior dev speaks their mind aloud as they type. When the senior dev disagrees, they let them reach a dead end then explain why it was not working. Another approach is to ask questions as the junior dev tries to describe what they’re going to do. They’ll inevitably doubt about the proposed solution. This way, they can understand by themselves it would not work and will actually learn. It requires a lot of patience and sessions should be definitely kept short, the exercice being so exhausting for both parties. At the end though, junior devs will be way more engaged and motivated.
The junior dev, mostly. Yet we all have different visions when it comes to problem solving and juniors can bring a breath of fresh air to a project you should not underestimate. Also, senior devs who’ve been part of the team for a long time well often share the same point of view on a code base and how things should generally be done. A junior dev, however, usually ask questions that force the veterans to explain what some portions of code actually do. This helps to detect design flaws early on that you wouldn’t have suspected at all. You onboard a new team member and at the same time review what has been done before, making sure it’s understandable and that it won’t all fall apart someday. Win-win.
Two juniors pairing together is generally considered a bad combination. They can’t rely on an experienced developer to help them sort their minds. On a complex story, when dealing with agile projects, they’ll lose time investigating each dead end. That generally leads to frustration and failure, also potentially increasing project risk.
A senior dev should approve the stories they pick, generally simple stories. It can work if the team is ready to accept errors and if the juniors already had prior pair programming experiences with a senior dev. They’ll be able to share with each other what they’ve learnt from their past pairing experience.
Also, there are always trade-offs to be made when dealing with development. When they have no senior dev around at disposal, junior devs have to take their own decisions. Something they could be reluctant to do when pairing with a senior, too worried to seem somehow dumb. Taking decisions is an essential part of the learning process when coding. It allows devs to build up their self-confidence.
Pair programming is a good practice to grow as a cohesive dev team. You want juniors to be more effective and expect someday they’ll be able to handle stories by their own, without systematically requiring you to fix everything afterwards. For this to happen, they first need to feel they are key elements of the project and team.
The last scenario I’ve not tackled yet is two senior devs pairing together. Although a senior programmer might be able to handle any story of a project, there are a few cases where pair programming can help: learn a new framework together, resolve bugs implying multiple code portions written by each parties or increase the bus factor.
Bus factor refers to the number of people in a team that can put a project in trouble if they disappear (literally by being hit by a bus but more seriously for vacation, illness or leave). Having a good bus factor value ensures the project will eventually come to an end. The rest of the team can easily take over the work done without being lost or having to restart from ground zero.
Pair programming helps to spread knowledge over the team and allows to increase the bus factor value. People involved on a project are no longer isolated on specific corners of the project and code duplication is avoided.
We often pair at USE Together just for the sake of increasing our bus factor. As developers, we have our own preferences when it comes to technologies, programming languages, frameworks. Pairing allows us to move out of our comfort zones, understand quickly how some piece of code is articulated and get ready to take it over when people are on vacation or simply working on other urgent stuffs.
There are numerous flaws we can potentially write when coding solo. We sometimes lack that step back that would have permitted us to quickly realize something will not really work as intended. When implementing a solution, developers have most of the time different approaches based on their experience. Two minds combined will help reducing massive show-stopper bugs.
Pair programming allows to share consistent coding practices between team members. When you expose some new way to arrange the project’s code during a meeting, people might not be as receptive as you thought they were. Pairing with them on a task that would, at some point, involve following your good practices will help them remember and understand the why.
Multiple techniques can be used to pair program. At any time, there are always one developer typing and one observing.
A classic one. The driver takes the keyboard and mouse control, writes code, navigates between files and mainly focuses on the current step to be done. The navigator, on the other hand, is responsible for reviewing each line of code being written and thinks more about the big picture: are we on the right track? Will that cause some bugs to emerge? What’s the next step? Driver and navigator often switch roles every 5, 20 minutes or each hour. It mostly depends on the pair but that should happen. Otherwise, the driver will feel exhausted quickly and the navigator will be bored and tempted to procrastinate.
This variant works best for senior-junior/newcomer pair programming. Basically, it’s analogous to driving lessons. The junior or newcomer dev is the driver and is responsible for writing the code. The senior dev is the navigator and gives clear instructions on what to do next, sometimes how to do it when the junior has absolutely no clues. After some lessons, the driver should have build up more self-confidence and know the main parts of the code base. The navigator then only gives a few tips when necessary. It’s important that the navigator resists the urge to take over the keyboard control. They should instead help the driver to figure out by themselves how things should be done.
In combination with test-driven development (TDD), a programmer is responsible for writing a failing test while the other implements the minimum needed for the test to pass. After a bit of refactoring, they exchange role: the person that made the test pass now writes a new failing test and the other one codes an implementation. Going back and forth, as a ping pong game.
The driver should speak their mind at any moment by explaining their approach. This way, the navigator can validate or suggest a better way to solve the problem. It requires some practice to rubber duck to a real person when you’re only used to speak with your brain. At the end, you will improve your own coding process.
Rest your eyes, drink, check emails, whatever but take breaks at regular intervals like 30 minutes or 1 hour. Constantly chatting and conveying your mind is exhausting.
We don’t think the same way, you should show some tolerance when your pair is taking too much time to solve an obvious problem. Maybe your pairing partner is thinking ahead about other issues that might arise or simply confused because of your irritation. Irritation is the first cause of bad pair programming experiences.
An essential skill for a programmer is the ability to search effectively on Google for docs, examples or similar issues as the one you’re having and possible ways to solve it. As the navigator, you might just be tempted to do that off-screen, say on your mobile phone, because the driver is indeed not searching for the right keywords and it’s exasperating you. Don’t. That’s an open door to distraction (oh I’ve received 6 emails). Instead, wait for them to find nothing relevant. Then, suggest new keywords and explain why you would search for that. Remember, pairing is learning and requires patience.
As the navigator, don’t insist too often on every mistake. The driver will figure out by themselves that a semicolon is missing or a variable is misspelled. Doing this too often makes the driver focus more on the code style than on the task itself.
Or zoom text. Especially when using high resolution screens. Hard to read when not exactly in front of the screen. If you can, plug in another one and mirror your desktop.
Use two mice and two keyboards to switch roles smoothly and at regular intervals (5, 20 minutes or 1 hour). But keep in mind you have one role at any time. Resist the urge to take over the control if you’re the navigator.
Keep the comfort of your own desk and overcome the last two points by pairing remotely with USE Together.