This article was inspired by a tweet I saw a couple of days ago that quoted Dave Farley and Kent Beck both stating that:
Pull requests are incompatible with CI/CD
I might be paraphrasing, so here is a video where Dave Farley explains his stance on pull requests in more detail. You can also find an interview with Kent Beck on the same channel.
The contents of that quote are not the focus of this post. However, that tweet got the wheels rolling in my brain, so I asked ChatGPT to list software development process practices and tools that have trade-offs. Pull requests, of course, were one of those tools (or mechanisms).
I’m here to write about some of those and have you think if these are really needed in your development work!
Pull requests
Pull requests are a mechanism of control that were invented to manage the flow of changes in open source projects. It was adopted widely by the organizations who work with proprietary software, even though it isn’t needed there.
++ Pull requests can improve code quality and help to catch bugs early, as well as facilitate knowledge sharing within the team.
-- However, they can also slow down the development process, as developers must wait for their peers to review and approve their changes.
To put that last part a bit differently: if your company’s review train is not moving at a continuous pace, you will be limiting your throughput. Developers might take on more work while waiting, which will lead to context switching. Context switching can lead to mistakes. PRs can also lead to developers just sitting on their hands while waiting for others to approve their work.
Pull requests are a clear trade-off. They are not the only form of code review, however.
Pair programming
Pair programming is the act of two developers working together on the same task, with one writing the code and the other reviewing it in real-time. You keep switching roles depending on the style you want to work with.
++ This approach can lead to higher-quality code, faster problem-solving, and better knowledge transfer. You also shorten the feedback loop and review your code as you work.
-- However, it can also be less efficient, as it requires two developers to be dedicated to a single task.
Some experiments and experts say that the claim about losing speed is false. They say that pair programming, while at start can be slower, will lead to the exact same results in terms of speed at the end.
Often the things you can ‘skip’ with pair programming is pull requests and perhaps even manual testing with QA. You already have two pairs of eyes looking at your code, how many does it need for your code to be approved for merging? You can then deploy your code faster and move on to the next item. This can at best save you day(s) in wait time.
You also now have two developers who’ve worked on that same piece of code and know it intimately. Any time there is a request to change it, fix it or extend it, they can both pick it up much faster. I would say knowledge sharing with pair programming is much better than pull requests.
Pair programming doesn’t work everywhere
There might be organizational decisions that can prevent you from doing pair programming. One of these is having developers work on only one vertical.
What this means is you have front-end developers, back-end developers, QA engineers, UI/UX designers and they all work in their own little area of comfort. Typically a team only has one person in each role which means you don’t have a chance to pair up with anyone in your team. If your back-end engineer is not comfortable with working on the React app with you, you’re out of luck.
In the perfect world we’d have autonomous teams who can hire the developers they need and form the team that they need, but most often teams are subject to management by the organization and can’t do their own hiring.
This is why I often promote that developers should work in more than one discipline in a team. This will not only enable pair programming, it will enable one developer to tackle any story that requires them to work on multiple verticals, and it will grow each team member’s T or M-shaped skills as well.
Feature branches
Feature branches allow developers to work on individual features in isolation before merging them back into the main branch.
++ This can make it easier to manage complex projects with multiple developers
-- It can also lead to merge conflicts and integration challenges.
Do you need feature branches? I say it depends. You can have them as an optional tool in any repo.
Again, this is a trade-off that should be evaluated in the environment it's meant to be applied to. I like to look at at least three things in any project for this:
- The number of developers working on the app
- The skill level of the developers
- The amount of automated tests
When you have a low number of developers working on the app, that often enables you to communicate between each other more effectively on the changes you make even on a daily basis. You trust each other to make changes that are of good quality and don’t harm the application.
You also need automated tests. These are in place to make sure you don’t break the application with your changes, but also bring you confidence in those changes. You need to run these with each commit in your pipeline if you don’t want to use feature branches.
The last one is the skill level of the developers. When I said that you can have feature branches as an optional tool, here is where they become effective. You can assign junior developers to work on the app and have them use feature branches, along with pull requests, to provide feedback on their work and to have better quality control.
Feature branches, or lack of them, can also be linked to the idea of continuous delivery. The concept of continuous delivery is best described by its inventor, Dave Farley:
Continuous delivery means always having your software in a releasable state.
When you skip feature branches, work on the trunk directly and embrace the idea of continuous delivery, you will work on keeping your software in a releasable state at all times. This means when you commit your changes, your CI pipeline validates your changes by building and testing those changes, and that provides you with feedback saying it’s ready for deployment. You work in such small increments that any possible mistakes are easy to fix and the blast radius is limited.
This is also called trunk-based development. You can use feature branches with trunk-based development, but more often I see them being paired with pull requests and the code review train making too many stops. Your branches end up living for multiple days, sitting in that queue, maybe hitting a conflict as other work gets merged into trunk. Also, any feedback you get will delay merging even more, making your branch live out even longer.
Scrum sprints
Sprints were introduced to us by Scrum. They are a commonly used methodology in software development that involves dividing the development process into short, iterative cycles of work.
They are a time box for development, where we should complete a certain amount of work that we’ve agreed to as a team. We try to plan the work to that small time frame before we commit to it.
++ Sprints can help you be more organized. They offer a sense of urgency and focus on delivering work (which can be beneficial for some). They offer management a way to see what the team will be working on during this and the next iteration. Sprints also offer a path to provide more structure to the development process by adapting more of Scrum to it.
-- Sprints create additional pressure on team members to deliver work quickly to keep promises and complete their sprint goals (which might affect quality). They introduce accountability and limit your scope by delivering a specific set of features within a fixed period which can result in incomplete or wrong features as often you only receive feedback at the end of the sprint.
What baffles me with sprints is how widely they are used and nobody really even stops to ask why. They are not actually needed. You can just as well do software development without this time box.
Often what I see is this time box is being mandated by the company, because they treat software development like any project they need to manage. It’s not actually used by the team out of necessity to make the development process smoother.
If you like structure and organizing the work into smaller buckets, Scrum as a framework can suit your needs better where you can also continuously improve the process.
On the other hand something like Kanban offers more flexibility with no fixed iterations or timeboxing, and also allows for more continuous delivery of work, with smaller batches of work being delivered more frequently. This can provide faster feedback loops and reduce the risk of long delays or unexpected problems.
Best development practices are about speed
Accelerate - The Science of DevOps: Building and Scaling High Performance Technology Organizations book, which summarized the State of DevOps reports, has told us that high performance teams have/use:
- Automated deployment process’
- Continuous integration
- Trunk-based development
- Test automation
- Continuous delivery
- Limit WIP
To put this in another way: to have good quality, you need to go fast. Automate as much as you can so you can deploy as quickly as you can without manual stops for quality control, with good focus on the work that you’re doing at that given moment.
While pull requests might offer you better quality control, they will hinder your performance. While feature branches make it easier to manage development with multiple developers, it can lead to merge conflicts and integration challenges that might hinder performance. While sprints offer you better organization and structure, Kanban can give you faster feedback and more flexibility.
Again, it’s all trade-offs. That’s the space we work in. Know what you’re giving up when you adapt one practice and don’t just be a mindless zombie that follows the mainstream because that’s how everyone else is doing it.
Top comments (0)