Of course, pair programming is not just about two devs sitting together and writing code in turn - it's a science and a fun-filled (well, almost) engineering practice. It has a lot of principles to follow, and if only the devs in a team can apply those principles correctly, can they benefit from it.
I'm not going to discuss how the pair programming affects productivity, or whether you should adopt it in your next project, or to what extent you should apply it in your own project. This article is for those who have already decided as a team to give it a try and are wondering how to do it, or for those who found that it is not as practical as it sounds, and want some useful guidance.
Firstly, you will need an external monitor and a height-adjustable table (ever tried making a DIY one with cardboard boxes?). This is neglected by most beginners; however, this is a fundamental step that can determine whether the practice is sustainable or not. If you have been staring at the monitor for too long with a poor posture, the pain will distract you from the coding, and you will find it more difficult to focus. So it won't last long if you’re uncomfortable.Before you start coding, make sure the screen is at an optimal height and adjust the height of your seat to make it suitable for you and your peer. If applicable, you might want dual screens.
Remember, pen and paper are your best friends. Firstly, it's crucial to split a story into S.M.A.R.T (Specific, Measurable, Achievable, Realistic, Time-related) sub-stories before you even start coding. Sometimes it's convenient to keep this posted underneath the bottom of your screen. Finally, please make sure your phone is in silent mode (this helps a lot!).
Please note that this technique only works if both of you have sophisticated keyboard (shortcut) skills. Another common scenario is when one person does not master any predefined keymap at all; this would require the ‘slower one’ to try to learn at least one keymap, and catch up with their peer.
Before you pair fluently with your peer, you should get familiar with one IDE/editor. For example, you should be able to do the following commonly used tasks without touching your mouse:
And so on, which would improve your productivity significantly. Even better, the ROI of those tasks is pretty high, so just take some time to practice and master the basics. Trust me, it's worthwhile.
So that’s enough for the setup, now let's look at pairing. Ideally, peers should have a similar level of skills, have a relatively similar level of knowledge, and can communicate fluently and effectively. They can focus on the problem itself and discuss deeply, bounce ideas off each other, and let their fingers dance when they code. In scenarios like this, they don't need any techniques and are free to work in whatever form they like.In contrast, there are scenarios where both peers have no idea of how to solve the problem, and neither of their skills fit the project's requirements (something we should avoid when staffing).
Sometimes it's pretty easy for a driver to become too immersed in their work to ignore the peer’s feelings. Frankly, I do it myself as well (which is terrible) and can often end up treating my peer like a ‘rubber duck.’ This can make your peer frustrated and unable to follow your pace, which would ultimately affect the outcome. As a driver, you need to be more patient, and continue engaging with your peer.
The other extreme end is where the driver is too passionate to coach, and they neglect to create an opportunity for their peers. This requires the driver to introduce more opportunities for the observer to practice. For example, after going through a complete test-driven development (TDD) cycle (red-green-refactor), suppress your pulse to continue coding (I know it’s hard), give the keyboard to your peer, and ask them to follow exactly what you just did.
When you see something go wrong, you should immediately stop your peer, and try to make a suggestion like:
If they hesitate or cannot quite follow, try:
As an observer, pairing is a great chance to learn from your peer, so you should make the most of the experience. For things such as keyboard short-cut usage, options for command line tools, or any other productive programming habits your peer has been using - keep an open mind and be curious. And when you see you peer magically delete all of the content in brackets, or pretty up the output from curl, don't hesitate to ask.
In practice, you can switch your role at every test and code cycle. For example, A writes a test, B codes to make the test pass, and A does the refactor, then B writes another test, and so on so forth.
Once you have decided on what the problem to solve, you then need to do the tasking. This will make sure you always focus on a small chunk of work and avoid any potential waste when you have to switch between contexts.
Once a task is done, just cross it out from the sticky note. Don't underestimate the power of those cross-offs. Firstly, it can easily visualize progress. Secondly, it acts as a reminder whenever you’re interrupted by your surrounding environment. Finally, this small ritual could provide your brain with positive feedback, which can promote dopamine that can make you happy!
When you have to pair with a stubborn colleague, or even perhaps you are somebody that is difficult to convince, how would you handle the arguments likely to arise? Especially those arguments where you cannot determine what is right or wrong clearly, for example, which programming language suits the most in Web application (I mean, surely it's PHP, right?), or how to do TDD properly (bottom-up or top-down) and so on.
In some situations, we insist on something we genuinely believe in and treat others who don't think in the same way as pagans. Actually, it just takes a little more time to realize that they might not be so wrong, and that it may make more sense if we could see the problem rationally from another angle.
In one of my previous projects, I chose the scss module as the CSS preprocessor just because in a previous project I used it and found it pretty handy. While one of the colleagues proposed styled-component, we were unable to convince each other. So we ended up having both styles mixed in the codebase. Until one day, I found that component built on top of styled-component looks pretty neat, and after trying to refactor some of the components written by scss to styled-component, I found that the code looks more concise and doesn't have any impact on existing tests.
Suddenly I realized that the truth I had been insisting on was like a fantasy I had made up, just so I could keep on using something familiar. Having an open mind is not that easy, and I hope that you can take a step back to rethink the proposal you made when you find that it's hard to convince others or be convinced yourself.
For those hard-to-agree dilemmas, I suggest you park it and try one of the approaches, until you find out what is blocking the implementation of the business requirement. Usually, you will find some trade-off, and come up with a solution by playing to each other’s strengths.
Even for experienced developers, they will face tough problems such as dealing with a new domain with a complicated business logic or even new challenges in domains that they are already familiar with. In some cases, both peers do not have any clue on how to get the problem solved. If you insist on pairing at this stage, it actually makes it difficult and ineffective.
One viable approach is to do some ‘spikes’ separately within a limited time box, say 30 minutes. In most cases, at least one of you will come up with some direction to start with. Otherwise, you might have to raise it as a technical risk to the whole team or the whole program.
For instance, we were facing an authentication issue about Kerberos, neither my peer or myself had ever done this at all. After 20 minutes of separate studying, I found an informative article covering a lot of details about the Kerberos authentication mechanism, and my peer found some existing code in internal GitHub. We decided to copy that code instead of putting more effort into it and refactor it later on.
Attention is actually the most precious resource, normally you can hardly focus on anything more than 30 minutes. After that, your brain will find something more interesting instead. A short break could help the brain rest and refresh. Our brain has a fascinating feature: it has a super ability to handle tasks in the background (a.k.a our subconscious), which can be surprisingly more powerful than what happens in the conscious part of our brain. Chances are, you have already experienced many ‘aha moments’ when you’re going downstairs for a flat white, during a shower, or even in your dreams.
When you encounter some bugs that are difficult to understand or you’re stuck with setting up the testing suite, taking a break might give you some inspiration by looking at things at a different angle. To avoid being immersed too deeply in a particular issue, you could use tools like 'tomato timer' or similar tools:
When you always pair with someone for a while, the pair has the risk of turning into an ‘information island’. For example, let's say A and B have been working on order modules, while C and D have been working on store management. After a certain period of time, A and B won't know what C and D are working on. This includes not only domain knowledge but also technical details/design patterns, etc. When your team grows to a size of ten or more, the problem of having an information island could get worse.
You should have some mechanism to ensure pair rotation happens, for example, rotate the pair twice a week or so, in order to enable knowledge sharing across the team.
In some cases, the team will adopt front-end and back-end separation. The tech stack in both ends may have nothing in common, which introduces potential challenges for rotation, and this can reduce productivity in the short-term. Things could also get worse when the Ops are separated as an independent team.
In practice, I found that pair rotation among different roles can help widen an individual’s knowledge and viewpoint, and as much as having a specialty is great, we need to encourage each other to learn and share as much as we can. If a front-end developer spends some time pairing with Ops, they could understand more about how the application works at the architecture level. And after the back-end devs pair with the Ops, they might be able to identify potential defects and fix it even before the defect happened (for example, externalize the session storage, cache strategy, etc).
Learn to see things from your peer's perspective. Try not to be the person you don't want to pair with. For example, the person who is always using the mouse to navigate files and is less effective when typing or the person who is careless with their typing if they are following you - the point is, try not to be that kind of person yourself.
Apart from this, respect comes from all of the smaller details. When you have to leave during pairing for something else, make sure to let your peer know, and apologize before you leave. Don’t just vanish and show up later. No one wants to pair with someone who isn't reliable. Furthermore, when your peer comes back from a meeting, you should tell them what's happening, give an update on the progress, and what are you trying to do next. Make sure you have the same understanding on the task on hand.
Emotions are an interesting thing, and it can easily propagate to others. When you have a few blockers preventing you from trying to finish the task, or you're finding it difficult to make any progress, you have to learn how to control your emotions. When your peers complain next to you, it makes you also feel frustrated and difficult to focus on solving your own problems.
It's crucial to seek help outside and visualize the blockers. Let the team understand your situation and provide support, if possible. Be proactive on the task itself and try not to influence others with your negative emotions.
After a full and happy day, it's your responsibility to summarise what you’ve learned - this is a perfect way to improve yourself and skill up. After applying the knowledge and experience you gained to a real-world project, you can find areas of improvement and learn how others solved similar problems, and this will have a profound impact on your learning and growth.
For example, when you are quite comfortable with using grep to do full-text search, and noticed that awk looks more effective when your peers demonstrate the advantages of using it. You can then go back home and try to use different options or compare this with the tool you are already familiar with. Another example could be you and your peer found an interesting feature about webpack when fixing an issue, but neither of you understand the mechanism under the hood - this is also a great opportunity for you both to learn and grow. Spend some time updating your technical skills by learning from others, which will help develop your skills for the next day’s pairing - and have fun!
Those principles are fundamental, subtle and might seem a little trivial. But doing it well can make you and your peer comfortable and confident during pairing, and hopefully enhance productivity into your daily work.
In this article, I summarised some common patterns and things you should do during pairing programming. Here are the seven key takeaways:
By applying these principles, it will be helpful for both the individual and the team in the long-run, and promote everyone to work in a healthy, and even happy, environment.
Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.