I’ve spent nine years working in teams which religiously follow pair programming. I’m used to working that way and appreciate the benefits it brings.
We didn’t have the luxury of pair programming all the time in my last project. This required us to do code reviews to ensure the quality of the code we delivered. This post is an attempt to consolidate the upsides and downsides of doing code reviews instead of pair programming in my three months of experience.
We use Github as our source code repository. The master branch is always considered to contain production-ready code. Each story is developed on an independent branch, a pull request is created, reviewed and merged back into the master.
We use git-reflow to facilitate code review. Working on a story typically involves three steps:
Start — You do a
git reflow starton master. This creates a new branch with whatever is on the master branch. You can continue working on this branch and it should not affect what is released to production since only changes that are in master go to production. Our CI(Teamcity) was configured to run the build on every branch that is created. So as and when changes were made, the tests were run and verified.
Review — After completing your changes and reviewing them yourself, you can raise a pull request by running
git reflow review. This will create a pull request (PR) on Github. You can then ask any of your team members or a particular person to review. They will put their suggestions/comments as inline comments on the PR. You can have a conversation on whether any changes are required. This generally goes back and forth between the developer and the reviewer. Once all the required changes are done, the reviewer marks that the PR can be merged by adding an ‘LGTM’ comment on the PR.
- Deliver — You can now merge the PR into the master branch. You might have conflicts if someone else has merged and made similar changes. After a successful merge, you have to make sure the expected functionality is working on master and all the tests pass.
You can find more information about git-reflow in these posts:
- Specialist feedback — Although it is encouraged to have more generalists in an Agile team, it is often advantageous to have some specialists or people who are experts in some areas like CSS, database, or rails. And having a setup like this helps in getting their feedback on the code before merging. This encourages sharing of knowledge. I’ve found this to be more scalable than getting the specialists to pair with each member of the team. This also applies to teams where there are more junior developers than senior developers who may need feedback on the code written.
- No keyboard hogging — Pair programming is useful as a way of sharing knowledge. But I have seen sometimes people with more experience dominate the pairing. Although it is great in the beginning to share knowledge, it doesn't help junior folks build the confidence to work on their own. Even if they are given a chance to navigate while pairing, they might feel some pressure because they are wasting their pair’s time to keep up to their pace. When following code reviews, junior folks can work on the stories by themselves. They can get occasional help if required and also spend more time reading outside core working hours without the guilt of wasting their pair’s time. They might initially take more time to deliver a story but it helps in building their confidence.
- Suits distributed teams — I have done a lot of remote pairing. Even though it works well, you often have timezone and bandwidth challenges. Since code reviews with pull requests are done asynchronously, they also allow team members to follow working hours that are convenient to them.
- Conversations are archived — Pull request comments are useful for someone to know why things are done in a certain way later.
- Highly collaborative — The conversations in a code review are visible to the entire team. If there is something I can provide input on, I can jump into the conversation. This happens in pair programming when the entire team is sitting in one place and conversations can be overheard. But it’s not always possible for distributed teams.
- Working on stories which have dependencies is hard — There might be an in-progress branch from which you need changes, but you can’t get them onto your branch because they haven’t been merged to master. This requires the developers on dependent stories to work very closely and a lot of git merges and rebasing.
- Time lag between story development and review — This often happens because people are busy developing their own stories. You sometimes have to follow up with people multiple times to get the review done.
- Reviewing big changes is hard — If there are a lot of changes, it takes a lot of time and effort to review them thoroughly.
- Delayed feedback from CI pipelines — CI pipelines for every new branch works great only at one level. If you have a second level build which runs end-to-end tests on multiple services, you cannot run them on all the new branches. Hence, the feedback is delayed.
This doesn’t mean we shouldn’t do pair programming at all. It still helps to pair when you’re on-boarding new people or setting up a new code base. And I feel it is still useful to do some form of code review in teams that follow pair programming. But make sure you keep the stories small and don’t end up having long-lived branches.
Please add your thoughts in the comments. And if you like the post, recommend it so others can find it participate in the discussion.