Pair programming at Codacy and why we do it
Pair programming, also known as pairing or “dynamic duo” model is not a new concept, and it was pioneered by C/C++ guru P.J. Plauger (Scott W. Ambler, Larry Constantine, 2001). This practice consists of two developers working together off of a single screen: one is the driver, who actively codes, whereas the other, the navigator, provides instant feedback.
Once teams focus on making pair programming work and get the dynamics right, they can reap multiple benefits from it.
In this post, we will uncover how all of our Product teams gathered to brainstorm about this technique and the advantages we came up with. It is important to address here, that pairing isn’t necessarily a concept exclusive to developers; anyone can pair, whether you’re in HR, Finance or Marketing, and right now, as remote work is more embedded than ever in our society, this is probably the best time to try it out.
We already had some development teams experimenting with pairing in the past and, as we went fully remote over two months ago, we thought that this concept made even more sense for others to try it out. Acknowledging its strong reputation, we wanted to encourage all the teams in Engineering to also experiment and adopt pairing, and eventually scale it to other departments. At the end of the day, this could be an opportunity for people to keep a connection with each other while working away from the office.
Facing the current “work from home” scenario, we decided then to join teams virtually, starting with the different development teams. Through a workshop format and breakout rooms with random groups of four or five people, we had everyone collaborating, sharing experiences and knowledge around Pairing.
As an outcome, we uncovered some of the benefits of this technique, why we should adopt it, and what makes it work. This was turned into a chapter in our handbook for everyone to refer to when pairing and to serve as a basis for every pairing experience at Codacy, whether in person or remotely.
The positives of pairing
- We improve knowledge sharing, effectively helping each other grow
We are able to shorten the learning period of our codebase and therefore improve the onboarding.
- We decrease the bus factor
By constantly working side by side, and being able to proceed with work if one person is unable to work on a given day, this makes us much more resilient as squads and as a company; over time it will be easier to have each other’s backs whenever needed.
- We make our reviews easier and simpler
When we pair, we’re discussing and getting real-time feedback on the work that we’re doing. This helps to improve the quality and speed of delivery because we find issues sooner rather than when we request a review.
- We work in a more focused way
We already knew reducing the amount of Work in Process (WIP) makes us go faster and be more efficient. When we pair, there are fewer streams of work open in parallel. That means we’re more focused on delivering the most prioritized features and can maintain the workflow.
- We deliver better work when we do it together
We’re excited about having cross-functional teams that can deliver a feature from start to finish. Pairing allows us to not just learn from each other, but also to increase the discipline of our practice, and do the right thing together.
- We get much faster feedback
With pairing, we’re able to shift left and bring quality sooner rather than later. This brings much higher quality upfront, avoids making mistakes and later fixes, therefore also improving our speed.
- We increase out teamwork levels
We go back and forth trying to solve a problem together, which increases empathy levels and improves relationships. This leads to a better understanding of each other, creating cool and fun dynamics between people in the squad.
Especially when pairing remotely, there’s a higher sense of productivity since we’re helping each other move forward with the challenge at hand.
- We become better synched
Since we’re rotating pairs and we’re tackling things together, we inherently become more in sync with each other. Chances of being blocked are reduced and the overall alignment is better.
With the benefits listed, the next step was to understand how we would make it work and get the most out of it, considering the challenges that may arise.
There are a lot of behaviors and practices that contribute to a great pairing experience and that boost the quality and resilience of our squads.
What contributes to a great experience
- It’s important to define the roles
It’s useful to have a pre-agreed set of guidelines on the pairing roles: Driver & Navigator. This helps in having a better understanding of the duties of each member, reducing friction and discussions whilst helping to focus on the challenge to be solved.
- Communicate constantly and use clear, visual language
Thinking out loud, constantly speaking your thoughts, whether you’re the driver or the navigator, creates a guiding line for the reasoning of the pair and the work being done. It also helps you catch loopholes on your internal reasoning.
- Remote preparations
It’s important that you’ve got silent conditions and a good microphone (make sure you test it). Remember that someone else is going to be looking at your screen, so adjust the resolution or font size in order for the other person to see well.
Visual cues are incredibly important, so make sure cameras are on and you can see each other while screen sharing. Try to keep the distractions for both people at a minimum.
- Pairing dynamics
Before starting the pairing session make sure you’re both aware of each other’s schedules. Agree on a time for breaks, and respect those agreements.
To avoid getting distracted or creating an uneven dynamic, rotate frequently between the driver and the navigator. Set a timer to trigger a rotation at least every 30 minutes. Base your rotation on time, not completion of a task (to prevent never rotating).
- Be collaborative
It’s really important to be open for some collaboration, accepting that there are going to be fewer parallel streams of work and a sense of speed decrease. The benefits outweigh these, so keep them in mind because you’ll be triggering feedback earlier and avoid possible rewrites of code.
- Boost knowledge sharing
Pairing is an opportunity to help someone become a better professional and also to grow by learning from someone else. This openness to learn and teach is crucial for the pairing dynamic to work.
It’s also important to note that, in case someone knows way more than its pair, the person with the least knowledge should be encouraged to assume the driver role for longer.
- Keep your mind open for all ideas
We all have different opinions. If we feel they are listened to and taken into account, we’ll be more willing to reach a compromise.
- Rotate pairs frequently (e.g. twice a week)
Schedule the rotation of the elements of each pair. Make it dependent on time, not on task. If you’re halfway through a task when you’re supposed to rotate, simply choose which member of the pair continues working on it with their new pair colleague. This will also help to boost knowledge sharing and resilience in your squad.
- Constantly improve, and share key learnings with the team
Focus on improving pairing over time. Have debrief moments after each pairing session, understanding what can happen to make it a better experience next time. Sharing this helps to build trust in each other and to create better dynamics.
- Align work with your squad
It’s relevant to communicate beforehand which tasks will benefit most from pairing and when each person is available for pairing. Use refinements to signal which tasks must be tackled in a pair.
- If things go wrong
Ask someone else’s help to ease any conflict that might have occurred. Remember that each person has different needs, personality and working styles, so it’s normal that you need some time, practice, trust and love in order to make the pairing work.
In this session, we fostered a moment where our squads shared their experience and lessons learned with each other, giving us the ability to understand more notably the advantages of pairing. This allowed everyone to increase their ability to pair, or at least encourage them to do it more regularly, knowing they have these guidelines as help, and more importantly, the rest of the organization supporting them.
At the end of the day, by engaging with this technique, development teams can avoid later fixes, reduce bugs, consequently improve speed, and cut the overall cost of programming. We’re already seeing some of these, and as an example, in the last few weeks, we reduced massively the number of new bugs, seeing up to a 75% reduction. Of course, this can be attributed to other factors as well, still, some of the results obtained after we started pairing have been remarkable.
In addition, pairing empowers our team members to grow in a shorter time span while contributing to social interactions. This also contributes to increasing the resiliency and knowledge of our teams and organization: when you pair, you are learning from, discovering with, or teaching someone else.
Having all of our different engineering teams embracing this technique was an achievement and the feedback is very positive. It also impacted our company culture, so much so that our next goal is having all of the other departments in the organization also trying it out, by following these insights we just shared. As we touched upon in the beginning, the truth is, anyone can pair and see benefits from doing it, regardless of the department one is in.
A number of people helped with this content, without them this wouldn’t have been possible. Thank you, team, for all of the insights and for proofreading and editing.