Over the past few weeks, I’ve been thinking a lot about effectively maintaining shared code within an organization. For example, think of a private npm package that multiple teams depend on. How can we ensure that changes to shared code made by Team A don’t break Team B and C’s code? And how can we make the process of updating all related codebases as painless as possible?
The more I think about it, the more I’m convinced that the most effective solution to this problem is to make the team that introduces the breaking change responsible for updating all affected projects.
However, when I tried to pitch the idea to my coworkers, I sensed skepticism. So, to gather more feedback, I decided to start a Twitter poll:
Suppose Team A needs to make a breaking change to a shared code library (e.g., private npm package with components or CSS):— Markus Oberlehner 🔭 (@MaOberlehner) August 19, 2021
Who should be responsible for making necessary updates to code primarily maintained by the Teams B, C, and D?
(all teams are part of the same company)
The results are clear: most people believe that each team should be responsible for cleaning up the mess created by Team A. Since I already knew that this idea is not the most popular one, I wasn’t surprised by the result. Still, I find it somewhat counterintuitive. I can’t think of many human endeavors where it would be deemed acceptable behavior to apply the same principle of Inversion of Responsibility for cleaning up, from those who caused the mess to those who mainly suffer from it (at least in the short term).
Socially Acceptable Behavior Among Software Developers
Suppose you have three kids: Kid A, B, and C. Kid A scatters all its Legos, not only in its room but also in its siblings’ rooms. I would be surprised if, under these circumstances, many people would argue that Kid B and C should clean up the mess caused by Kid A.
Why do we consider acceptable among developers what would be unacceptable in most other circumstances, even among children?
The only other example I can think of, where we apply the Inversion of Responsibility (IoC) principle, is air pollution. As a society, we find it acceptable to allow people to drive through densely populated areas in machines that emit exhaust fumes that have been proven to cause serious diseases such as cancer and are a major cause of premature death.
What both examples have in common is that:
- those who do the most harm benefit the most from IoR;
- on the surface, it seems impossible to do it any other way.
Holding drivers accountable for cleaning up the air pollution they cause is next to impossible. So we just accepted it, thinking it would be too difficult to do it any other way—a pretty strange arrangement.
With shared code, those who introduce the most breaking changes benefit the most from offloading the responsibility of updating affected projects to other teams. And it seems impossible to do it any other way because a single team can’t possibly update the projects of 10 or more different teams all by itself. At least that’s what we tell each other.
I’m afraid I have to disagree with this sentiment. We should learn from the car analogy that it is unacceptable to throw out all social norms just because we (allegedly) can’t do something any other way. Cars that emit carcinogenic gases probably shouldn’t be allowed to drive through densely populated cities. Teams probably shouldn’t be allowed to make breaking changes without taking full responsibility for updating all the code they break. If we think that’s impossible, maybe we can invest more time into improving our tooling and try to automate as much as possible.
Also, what “taking full responsibility” means precisely can be discussed. I think that by default, we should expect teams to make any necessary changes themselves and merely inform the other teams of what they have done. But depending on the nature of the change and the maturity of the tooling available (less mature tooling may render it unrealistic for a single team to do all the work), it may also be acceptable for the responsible team to actively support other teams in updating their code.
Wrapping It Up
I think we need to apply the same social norms we rely on in most other areas of life to our development processes:
You Break It, You Fix It.