This article on reducing merge conflicts is part of a series on How to Choose Your First Microservices.
Switching to a new software architecture style is costly. I advocate choosing where to employ microservices first by using them to solve existing problems in the team. This helps the organisation extract value from the new architecture with each step towards the new world. This series is working through a set of problems that your org may have, and how microservices might help solve them.
Is your team wasting a lot of time working around each other?
If you have a large team of developers working in a single code base, it’s inevitable that the work of some team members will interfere with the work of others. Many of us are now using tools (like git) and processes (like continuous integration) that can lessen the impact of interference. (Although other modern practices like feature branching can make conflicts worse.)
Despite improved tooling, merge conflicts are still annoying and sometimes expensive to recover from. Everyone fears finding someone else has been making wholesale changes to code that they were also making wholesale changes to.
This can get exacerbated when people from multiple teams are working in the same area of a codebase. It’s especially true if the organisation isn’t set up to encourage regular communication between such teams. And the more your monolith’s internal architecture looks like spaghetti, the more people will bump into each other’s changes.
How Microservices Reduce Merge Conflicts and Enhance Collective Ownership
One of the key advantages of microservices is that it places natural limits on the amount of cross-team interference. Giving teams their own codebase/s to work in means they know that only the people they work closest with will be changing the same repository.
The first problem this (obviously) helps with is reducing merge conflicts. Conflicts cost time to resolve and increase the risk of defects, so minimising them is a good thing. The other issue it can help with is the pressure that regular interference puts on collective code ownership. I’ve seen developers avoid making improvements to code because they want to limit the chances of a merge conflict. With their own codebase, developers have the confidence to re-shape code so that it’s the best design it can be. There is a scale beyond which collective code ownership doesn’t work for a single codebase. But that doesn’t mean you should abandon it. What’s better is to create smaller scopes of code and teams within which it can continue to work well.There is a scale beyond which collective code ownership doesn't work for a single codebase. But that doesn't mean you should abandon it. What's better is to create smaller scopes of code and teams within which it can continue to work well. Click To Tweet
If you’re hearing that developers stepping on each others toes in a monolithic codebase is causing a lot of pain, here’s what you can try. See if you can find upcoming work that will allow one or more of the teams to develop almost completely outside of the existing system. You might even decide that the team working on the new service won’t do any code in the monolith. Instead, they can rely on one of the other teams to implement any changes required in the existing code.
Here’s an Example
When I first led a team at Tyro, we had recently split into three Engineering teams. Two of the teams were working almost full time on our big backend monolith. The third team would also jump in there from time to time as needed to support their work. It was a big repository, so we didn’t butt into each other’s changes every day, but it did happen. It also made other things more effort than they should be. When the build broke, or an alert came in from production, deciding which team should respond wasn’t always straightforward.
Right at this time, a new project came up to build a private health claiming solution. This was a new product that would integrate with our existing payment products, but also be distinct in many ways. Though it would need to integrate with the existing monolith, we made the call to develop as much as we could in new services. This resulted in three new artefacts. One was for handling online requests and was used by the software our payment terminals connected to. Two backend services were created for two different types of configuration that needed to be managed, one of which integrated with the payments backend monolith. The decision meant the team spent most of their time developing new software which other teams weren’t touching. There was almost no chance of conflict, except with the other three pairs on the same team.
The first thing to watch out for here is the same as when using microservices to resolve long build times. Avoid separating out something which requires some work right now, but won’t require much attention past the short term. If you do, you’ll only get temporary relief from teams stepping on each other’s toes before people return to working on top of each other in the monolith. Different services will (and should) have varying degrees of complexity and ongoing work based on how you define your bounded contexts. Some domains are simply more complex and/or will change more as the product evolves. If you’re prioritising to get teams off each other’s toes, you’ll want to look at separating out something that has a long-term development roadmap associated with it. That way, the team that builds it can stay in there and stay separate from other teams for an extended period.
The second thing to watch out for is creating a distributed monolith. By that I mean code deployed as separate components but which is tightly coupled in the way it operates. You don’t want development of features to regularly require changes across a large number of services. If it does, you’re still going to end up with multiple teams working on the same pieces of code and getting in each other’s way.
If you want to be notified when future articles are published, sign up using the form just under my photo.
Previous article in this series: Using Microservices to Solve Slow Build Times
Next article in this series: Using Microservices to Make Costly Deployments Less Frequent
‘Car Crash 7-1-18 2252‘ by Charles Edward Miller