Pull Request-Driven Development
At my new job, I’m working on a project that uses some different processes than the project I was on at my last job. I’m finding the differences interesting, and have been thinking about the forces that would push a team in one direction or another.
Background
Process
Both projects use similar agile-style techniques: test-driven development (TDD), pair-programming, iterative development, etc. I would guess that both projects are similar in size (both code an feature-wise), though that’s really hard to compare because they use different languages and frameworks.
Team Composition
The new project has probably 3x more people working on it than the old project. Many of the developers on the new project are relatively new to the project, and some are even relatively new developers. The old project was pretty top-heavy in terms of development experience and longevity on the project.
Age of Code
Much of the code in the old project has been around for 15-20 years; the new project is not that old. That explains why the codebases are similar in size even though the team sizes are so different. I expect the new project will become quite a bit larger over time.
Version Control
The new project uses Git and GitHub for all development. The old project is migrating from Subversion to Git, but also uses Store, the built-in version control system of Visualworks Smalltalk.
Deployment
The new project is a web application. The live site is updated whenever changes are committed to the master branch.
The old project is software that runs on industrial equipment; our builds would always produce an installable CD image, but we actually deployed to the field much less frequently than that.
Development Style
Branches
On the old project, almost all work was done directly on the trunk (or “master”, if you prefer). We would create branches from time-to-time, but we did our best to work right on the trunk and keep everything stable. This forced us to work in small increments and find ways of keeping work-in-progress away from the end users until it was done (using “feature flags” and similar techniques).
The new project does everything on branches. There are some long-running branches for major new features with minor story branches off of those. Nothing gets committed directly to master; master is only updated by merging in another branch.
Pull Requests
On the old project, we considered pair programming to be a sufficient form of code review. Any pair could directly commit to the trunk when they were ready. If any code was developed solo, then we’d ask a colleague for a code review first.
On the new project, all code goes through a pull request, even if it was developed by a pair. Pull requests are reviewed by at least one other developer, often more.
Testing
Both projects have a way of deploying running software somewhere “safe” for additional testing. The new project uses internal staging servers; the old project had test equipment.
Impressions
Given a sample size of two, I won’t try to draw any deep, far-reaching conclusions from my experience. But I can talk about my impressions so far.
I’m getting used to working with lots of branches. Git does make that pretty easy; trying to do it in Subversion or Store would be much more difficult. But I’m already running into places where I want code from one not-yet-merged branch to be available on the branch I’m working on. Merges can also be a bit of a challenge, especially if you weren’t directly involved in writing the code that needs to be merged.
By far, the biggest adjustment has been having to have everything go through pull requests to make it into the product. I find that this really hampers flow.
I finish work on a feature, commit it to my branch, and push it up to GitHub. Then I have to create a pull request and wait for someone to have time to review it. Meanwhile, I start working on the next feature. Once the original PR has been reviewed, then I have to go back to that branch, remember what I was doing, and address any comments from the review. This can repeat several times before the feature finally gets merged. I’ve had 4 or 5 open PRs at a time already, and I find it difficult to keep everything straight.
This style of development also has a heavy impact on the developers who have been on the project the longest. They’re the ones with the deep knowledge of the codebase, and so they’re the ones best suited to review most of the PRs. That gives them a lot of extra work to do, and also means that sometimes the PRs can back up waiting for them to be available.
That said, I understand why the new project uses pull request-driven development, and I think it’s the best option given the constraints. There are lots of developers, and many of them, including myself, don’t yet have deep enough knowledge of the codebase to be able to make good decisions about the wider implications of the code they’re writing. On the old project, we had enough experts around that one of them was your pair partner for almost every story. On the new project there aren’t enough experts to go around, so having them review pull requests solves that problem. As a newcomer to the project, I really appreciate having the extra eyes on my work, because it’s easy for me to do something that doesn’t work in the larger context of the project.
But it still feels like it slows things down and I wish there was a better solution. Hopefully, as the team grows in their knowledge of the codebase, and in their development experience, we’ll be able to speed things up a bit.