Nearly every project I have been involved in has had either a shared module or DLL that was owned and maintained by everyone. The premise is always the same, reusing code to minimize waste and improve productivity. Is it always the case?
Before I can answer my own question, there are a few points to consider. I have primarily experienced two different paths in this regard. One in which the shared code was done and maintained by everyone and the other being when it was owned and maintained by the Tiger team.
The Tiger Team
This one is very “convenient” for the development teams. The shared module is available to anyone and if you want to do any adjustment all you had to do is call the Tiger team and they will do it for you. The problem is — when?
Imagine being on the Tiger team and getting requests from every other team. Your board is full of tasks that will enable teams to advance and all of a sudden, you’re the bottleneck. Not to say that, more often than not, you don’t have the entire context about what you’re trying to develop and if you engage in understanding that deeply, more delays can come.
Even if some flexibility is allowed, e.g opening the implementation for extension, it might very well be the case that they would have to approve what gets promoted to the core/common module/service.
The goal is still the same, reuse code as much as possible, but now, in an evolutionary design fashion. So almost anyone can create/maintain reusable components. Usually, architects and team leaders are the ones deciding what gets promoted to core/common so once a team needs something that could potentially be used by others, they do it locally and make it available afterward.
But what happens when two teams need the same architectural feature at the same time? what if a team changes something on core/common and it ends up breaking other modules? what if performance becomes an issue for team A and not for team B?
Almost everybody believes that code reuse is the answer to a more productive environment and that if we invest more time in this, it will pay off in the end. It sounds logical to assume that if you can reuse components, rework would be highly minimized. In practice, however, things don’t quite work that way. Even if you use code that was built by someone else you still have to integrate it, make it fit nicely in what you’re building and make sure everything is working properly — What do you do if it’s not? I have been on this side before, trying to fit an egg inside a bottle because it was done with that in mind.
Am I suggesting that nothing should be reused and everything should be built from the ground again and again? (the famous “reinvent the wheel” argument).
What Should be Shared (and adopted)
So far I have considered only in-house code but framework and libraries adoption, do fit in this category as well. There are millions of frameworks out there that promise to make our life easier. Some of them do, surely. It’s very likely that you don’t need to build a web framework nowadays, for example. This is a good example of shareable code, there are, of course, other minor libraries created by a group of people or even a single individual that is safe to use and deliver what it promises and you should use them — bearing in mind that your stakeholders do not care if code were inherent or built by you, if it breaks, it’s your responsibility to fix it.
For a multi-team environment, the mechanisms of communication shouldn’t be done independently. If you communicate through domain events, for example, the management of delivering those events to their respective subscribers should be equal in every module. But the decision on how to persist them or what to do once an event is received should be done in accordance with what is suitable for that particular team.
I tend to think of it this way:
If every team/module/service represents a house in a neighborhood, they all share the pavement. It’s everybody’s responsibility to maintain it. But no team should dictate how the insides of other houses should look like. That’s entirely up to the people who live there, after all, they are the ones who know.
Just like houses here in Spain which have separate heating whereas others have it central, where you don’t get to control either the temperature or whether it should be turned on. From what I know (and it is also my case) you don’t pay for heating when it’s central, that’s the only benefit of it, but in terms of flexibility, you get none. So what do you do in this case? You buy a portable one (or build one, if you translate it back to software) which is far from ideal.
The more I work on multi-team environments, the more I favor independence. It makes the process making technical decisions way faster and easier. The risk of breaking other modules is very minimal, leaving room to plan and execute precise solutions and being held accountable for it. So if it’s not working, you throw that out and don’t impact anyone else. It’s easier to prioritize things when they are small enough.