26 Apr 2018
Pairing: A Guide to Fruitful Collaboration đđđ
This post was originally given as a presentation at RailsConf 2018. The slides and video are also available.
When interacting with Ruby devs, Iâve heard a lot of feedback along the lines of âIâve heard that pairing is supposed to be good, but every time I try to do it I get more and more discouragedâ. Other devs Iâve talked to have lots of great experience pairing with their peers, but arenât sure how to work with someone more or less experienced than they are. The goal of this talk is to prepare you so that pairing is not only something that you can do with any other dev, but something that you want to do with any other dev. By the end of this talk, I want you to be ready have awesome pairing sessions where you are energized and excited by working together with other devs to conquer your shared problems. Pairing is a fantastic tool for your professional toolbox: letâs learn how to design, discuss, refine, and refactor⊠together.
So, before we dive in, why would you want to listen to me talk about this anyway? Iâve collaborated with other Ruby developers for 14 years, and for the last 5 years my day job has been almost entirely pairing. All day long, every day. In that time, Iâve paired with devs ranging from twice my age and experience all the way down to brand new devs writing code for the very first time. This talk is an attempt to gather everything that Iâve learned into one place, so that you (and, honestly, also me) can easily refer to it later.
What is pairing? We just donât know.
Even if youâve already been convinced that pairing is good, the desire to pair doesnât come with instructions. What is pairing? Itâs not incredibly clear, especially since asking 10 developers will usually get you 10 different answers. For this talk, weâre going to define pairing as working with another developer on the same machine.
If you havenât had a good pairing experience yet, this is probably the point where youâre thinking âwhy would you have two developers use one machine? only one keyboard and mouse work at a time, so one of those developers is just going to be sitting around doing nothing!â. In a good pairing session, nothing could be further from the truth.
Programming isnât pushing buttons, programming is solving problems. Itâs normal for more than one person to work together on a solution to a problem! Just think about anytime youâve had a productive conversation, exchanging ideas, learning, and finding new insights you couldnât have alone. Pairing is about bringing that experience to the work of solving problems with code.
Rather than one developer sitting around, both developers can be engaged with their work, communicating, planning, theorizing, end experimenting. Pairing provides many of the benefits of code review, with the fastest possible turnaround time and the easiest communication between author and reviewer. Another person can notice that youâve fallen down a rabbit hole and youâre far, far away from the problem you set out to solve. Rotating control back and forth can reduce fatigue from repeated actions, since it gives each of you a chance to sit back, read, think, and discuss.
Communicating your ideas to your pair means you are continuously ârubber duckingâ, explaining your understanding of the situation to someone else and having more ideas about what to do as a result. When your have a positive relationship with your pair, pairing also provides motivation to be the best version of yourselfâwith someone else watching, itâs harder to justify bad habits to yourself. Since future you is often the person who pays the price for your own bad habits programming, thatâs a win for everyone.
Pairing pitfalls
Itâs not all roses, though. Pair programming brings with it a new set of problems, and can magnify existing problematic habits. Itâs extremely common for a pair with uneven experience levels to degrade into one person working and one person watchingâmost likely without understanding what theyâre seeing, and without learning anything. Pairing with someone who is ideologically rigid can mean you end up in an argument about every single decision, and compromise is impossible.
When pairing with someone more experienced, itâs not uncommon to feel like youâre trapped in the interview or performance review from hellâit lasts all day long, every day. That pressure creates knock-on problems, like panic and blanking in the face of uncertainty, or shaky nerves leading to more mistakes. Pairing with condescending developers acting in bad faith can be a nightmare, and in those kinds of situations pairing provides social pressure towards bad habits instead of good ones.
The rest of this talk is to help you get to a point where you can maximize those benefits while minimizing those pitfalls. It will take thought, and effort. You wonât get it right overnight, and youâll need to keep thinking about it and working at it even after years of practice. All that work is worth it, though, because pairing can be one of the most positive and satisfying ways to experience programming.
Two people, working together
This is a great time to talk about the first and most basic requirement of pairing: you need two people who trust each other enough to cooperate and work together in good faith. You can only be one of those people! If your pair is condescending, discouraging, insulting, or casting doubt on your skills or abilities⊠thatâs not okay. If youâve ever been made to feel stupid, or like a burden, or like a lesser partner while you were pairing, that wasnât your faultâthat was the other person failing to be a good pair.
In addition, your pair has to want to work with you, and not want to work at you. A good pair has to be willing to share control, share ideas, and share credit. If your pair is not engaging in good faith, you have two options. First, you can call them out (if you feel safe doing that), and hope they listen and change. Beyond that, all you can do is find someone else who does want to pair collaboratively.
So! Letâs say youâve found someone who isnât going to condescend to you, and who wants to work with you instead of simply working while you watch. Awesome. The rest of my suggestions fall into three categories: pairing with similarly experienced devs, with devs more experienced than you, and with devs less experienced than you. The work you do is the same in all three of those situations, but behaviors that are helpful in one of them can be harmful in others.
Letâs start with the most straightforward situation: pairing with your peers, where you both have about the same amount of experience. Pairing with devs at your own level gives you the chance to swap tips, support one another in learning and growing, commiserate through the tough parts, and generally produce results that combine the best of what both of you have to offer.
Based on years of doing this kind of work, my experience is that good pairing sessions come down to consent and communication. Staying on the same page the whole time youâre working together will take some work, but it will help you produce better results.
To kick things off at the very beginning, you and your pair are going to need to communicate and consent about your programming environment. What machine, OS, editor, terminal, and shell are you going to use? Whose configuration files are going to be active?
If youâre going to pair a lot, the ideal is one dedicated pairing station per pair of developers, all running the same OS, ruby versions, editor, terminal app, and shell, all configured exactly the same way. This not only makes it easy to rotate who youâre pairing with, it makes sure everyone is able to sit down and start working at any time.
Itâs not ideal, but in a pinch you can also pair on someoneâs personal machine. I strongly suggest creating a separate pairing user account, where you and your pair can work out together what to install and how to configure things. Dropping someone directly into your own personalized environment (and expecting them to just deal with it) starts things of on the wrong foot. If you want to collaborate as equals, act like it! Level the playing field to include only things you have both agreed on.
Itâs not about writing code
Once you have a pairing environment ready, youâll probably be tempted to dive right in and start writing some code. Resist! This is one of the moments pairing can be massively better than working alone. Before writing any code, establish shared understanding about the situation. Articulate the problem you want to solve with your pair, and ask them for their feedback and ideas. Keep taking turns talking until you both agree on a shared understanding of the problem. That may just take a minute, but it might also require reading documentation, researching existing code, or even seeking out designers, PMs, or other stakeholders to ask questions and clarify requirements.
Right off the bat, pairing helps you avoid assumptions you wonât notice are wrong until youâve already built the wrong thing. Another perspective is one of the best ways to cover your blind spots. Reaching shared understanding with another person dramatically reduces the chances that you missed something without realizing it.
Once youâve come to an agreement about the problem youâre going to solve, work out guidelines for who will be doing the typing and who will be thinking about what youâre doing and narrating the actions and choices. Those roles are sometimes called âdriverâ and ânavigatorâ, analogizing to a common division of tasks when taking a trip in a car. Itâs not a perfect analogy, but it can be pretty helpful to think about dividing the labor up that way. Itâs much easier to notice things, good or bad, when one person is typing and one person is observing and contemplating the broader context.
One common approach is to combine pairing with test-driven developmentâin that scheme, one pair types while coding until the current red test is green and a new red test has been added. Then the driver and navigator alternate, continuing until the problem is solved or itâs time for a break.
Another approach, often called âping pong programmingâ, involves one person writing a test, and the other person writing as little code as possible to get that test green, back and forth. It doesnât work for everyone, but it can be very eye-opening to discover that the tests you thought were very thorough actually all pass when the code returns a single hardcoded value every time.
Now that youâre getting the idea, this is a good time to mention what is probably the most common problem while pairing: when you say âoh, let me just do this myself really quickâ, grab the controls, and do something yourself. No! Donât do that! Pairing is based on consentâyou canât unilaterally decide to take over the controls. As soon as you do that, pairing is over and the other person is just watching you show off.
Even if the person agrees to let you take over, though, itâs a terrible idea. The payoff of pairing is that you both understand not just what is happening, but why it is happening. If you canât or donât want to explain how and why to do something, you shouldnât be doing it. You might be feeling frustrated that something âsimpleâ is taking so long, but instead you should recognize the opportunity! This is a chance for the other person to gain new skills and new understanding. After this, either one of you will be able to do it.
Finally, both of your names are going to go on that code. It is the height of rudeness to ask someone else to put their name and reputation on the line for something they donât understand or canât do themselves.
Whichever option you pick, it needs to be clear to both people who is driving and who is navigating at any time. Trust and collaboration is hard to sustain when your keyboard and mouse are unexpectedly flying around underneath you and doing things you donât expect or want. At its most rigid, that could be a timer that tells you when to switch. At its most fluid, that could mean requesting and yielding control as part of the conversation, with control going back and forth anytime itâs convenient. When youâre doing this right, another dev could walk up to your pair anytime and ask âwhoâs driving right now?â, and both of you will not only give the same answer, but feel confident about it.
Now that weâve covered the mechanics of pairing and made some suggestions about how to pair with your peers, letâs talk about how things change when youâre pairing with someone more experienced than you are.
Pairing with someone more experienced
Pairing with someone more experienced is a great opportunity to talk through ideas, hear about new options for solving problems, learn about tradeoffs built in to different options, and see how devs who have spent more time at this job have chosen to adapt to it.
There most common pitfall when pairing with someone more experienced is the assumption that you have nothing to contribute. It will take work, but you can fight that feeling. The person youâre paring with should be helping you fight that feeling, too. Theyâre on the hook to make sure that pairing is a cooperative exercise, and not just a chance for them to try to show off.
While pairing with someone experienced, your main job is to provide feedback. Hear a word youâre not familiar with? Ask what it is. See something go by too fast to tell what it was? Ask to see it again. Notice your pair jumping in and taking over the controls? Point out they took over, and ask if they can help you do the same thing instead.
Just because someone has more experience than you doesnât mean theyâre automatically right. In fact, having more experience in some areas doesnât mean they have more experience than you in every area. When pairing with devs who seemed to know more than me about everything, I have and discovered strengths and specializations I didnât know I had. When pairing with devs just a few weeks into coding, I have regularly discovered that they have many kinds of experience and knowledge that I donât.
The bigger the experience difference is, the more important it is for both of you to make sure that your time working together is informative and productive for both of you, not just the supposed bigshot. Ask questions, give feedback, and work together to calibrate the speed and depth of your work so that itâs beneficial. You might feel like a burden, but trust me⊠the best part of pairing with someone less experienced is being able to introduce them to new things!
Another thing to keep in mind when pairing with someone more experienced is that they will know the answers to many of your questions. Rather than going straight to the API docs, or straight to Google, ask the questions you have. Humans are by far the best interface to information that you donât understand yet. Google can answer your question, but you have to know how to phrase your question to find the right results. People can help you figure out how to phrase your question, usually with much less flailing around.
If you run across something you donât understand, ask about it. Maybe youâll find out the answer. Maybe youâll figure out the answer together. Maybe youâll find out that even experienced people donât know a lot of stuff. Probably, youâll do all three. Take advantage of the experience that you have access to, and work together to reach a shared understanding of concepts and code. Thatâs what pairing is all about.
Pairing with someone less experienced
Pairing with a dev less experienced than yourself offers a chance to let them drive, helps you catch gaps in your planning, and makes you better at understanding and communicating your own ideas. Even though youâre more experienced, this is still a chance for you to learn, grow, and practice your skills. These are some tactics Iâve picked up that can make pairing with someone less experienced more positive, cooperative, and productive.
Before you start, establish cooperative, non-judgmental ground rules. Youâre going to be working together on two goals: one is getting the work done, but the other goal is giving the less experienced developer more experience.
Make it clear that computers are hard, you often donât know what to do, and if they donât know what to do while youâre pairing that is totally okay. If they pause, wait for them! If they pause for more than (say) 10 seconds, let them know that youâre happy to wait for as long as they need, but youâre also happy to start talking about what you could do next if they are feeling stuck.
Make it as hard as possible for yourself to jump in or take over. I have personally gotten a lot of use out of fidget toys or grabbing a giant stuffed animal to hug. In cases where my self-control is bad, I have sometimes even unplugged my keyboard and mouse. Itâs easy to not type when your keyboard doesnât work at all!
Finally, keep in mind that all of this work is ultimately a chance for you to level up yourself. High level independent contributor work depends on clear, persuasive communication. Pairing is a prime opportunity to practice and hone those skills. Coordinating development work across teams, gaining support for your policy proposal, encouraging developers to adopt good practices, and many other tasksâall require excellent communication skills.
Programming as relationships
Ultimately, software is made by people, for people. Every line of code is the result of some relationship between human beings. Working with a team means planning, communicating, discussing, compromising, debugging, and more. Even though it can be hard to tell when your up to your eyeballs in code, all programming is a relationship, with stakeholders, customers, managers, and coworkers. Pair programming makes more of that relationship direct and explicit, including both the benefits and the hazards that come from closer relationships.