If two Scrum teams use the same software component, who is responsible for providing a clear architectural vision of that component and maintain/develop this vision as the code base evolves? In Scrum you are supposed to have a collective code ownership, so how to make sure that development done by Team A doesn't interfere with development done by Team B?
I am not a Scrum expert, but AFAIK "collective code ownership" is meant to be per team and per product (and I think your question is not specific to Scrum, it could be applied to any "shared code" development process).
If you have two teams A, B, two products A, B and a shared component C, there are different possible scenarios. Maybe the shared component belongs primarily to product A (and is just reused, but not evolved, by the team for product B). In this situation team A is clearly responsible for the architectural vision. Or vice versa: it belongs clearly to product B - so the responsibility is there. If team A is responsible, team B might use a fork of the component to allow urgent bugfixes (there should also be a way to reintegrate them into the main line of C), but B should avoid doing any bigger evolvement of the component.
However, if both products A and B have a lot of "driving requirements" for C, you should manage C as a completely separate product, with own versioning, release management, change management, unit tests etc, and an separate team which has the responsibility for that component. That team could be just a "virtual team", consisting of separate devs from team A, B or both. This team has the "shared code ownership" for C, and the responsibility for the "architectural vision". Just think of C beeing a component delivered by a third-party vendor.
There is no concept of "clear architectural vision" in Scrum or agile!
I have long been an architect, and it's clear to me that in order to have have an architectural vision one needs to have a clear view of future requirements. Since in most cases the requirements aren't clear at all, it doesn't make sense to have a fixed vision.
What is necessary is to have an architecture which is adaptable enough to the changing requirements. In other words, things change, and the architecture changes - I am not advocating a "soft" architecture that can be reconfigured. I am talking about accepting that the architecture one has today will be obsolete soon and will need to be changed, so no one should "marry" to it.
Collective code ownership means that everyone should - in theory - be able to change anything. This has to be understood as the "opposite of silos". In other words, there can be skills barrier in place, which is normal and expected -- not everyone is an experienced DBA that can fine tune SQL queries, to give an example -- but from this it does not follow that only a DBA can hand optimize queries. There will be a "feature domain expert" that can help other people become proficient, but the tasks should still fall on everyone.
For example: if I am the domain expert on feature "A", then I still expect anyone else to do work on feature "A", but I am likely to be consulted when major changes need to happen or people need help. Feature "A" would certainly not be my feature. It will be a feature which I know well. It will be my interest to know many more features, and other people's interest to know this feature.
In synthesis: architecture is designed and redesigned multiple times by developers as the requirements emerge and change. Everybody is expected to make any necessary changes according to their skills, and know when to ask for help. There is no long term vision on the architecture because we trust the people and we do not trust the requirements.
For example, spotify uses a role named "System Owner" to solve the problem, directly from the document:
Technically, anyone is allowed to edit any system. Since the squads are effectively feature teams, they normally need to update multiple systems to get a new feature into production. The risk with this model is that the architecture of a system gets messed up if nobody focuses on the integrity of the system as a whole.
To mitigate this risk, we have a role called “System Owner”. All systems have a system owner, or a pair of system owners (we encourage pairing). For operationally critical systems, the System Owner is a Dev-Ops pair – that is, one person with a developer perspective and one person with an operations perspective.
The system owner is the “go to” person(s) for any technical or architectural issues related to that system. He is a coordinator and guides people who code in that system to ensure that they don’t stumble over each other. He focuses on things like quality, documentation, technical debt, stability, scalability, and release process.
The System Owner is not a bottleneck or ivory tower architect. He does not personally have to make all decisions, or write all code, or do all releases. He is typically a squad member or chapter lead who has other day-to-day responsibilities in addition to the system ownership. However, from time to time he will take a “system owner day” and do housekeeping work on that system. Normally we try to keep this system ownership to less than a tenth of a person’s time, but it varies a lot between systems of course.
I really like this idea, having the benefits or collective code ownerships at company level (not only in team level) but with this systems owners trying to ensure some architectural integrity.
A link to the complete document: https://dl.dropboxusercontent.com/u/1018963/Articles/SpotifyScaling.pdf , its a short but very, very interesting document based in real experience about scaling agile.
It's a difficult problem to solve, and it's certainly not solved by Scrum, which is a project management methodology, not a development methodology.
The most effective solution I've found is good package management (nuget/gem/etc) and versioning. Never enforce a change on another team until they're ready to consume it. Let them keep using the old build, while you move onto the new.
Make sure that you have a versioning strategy that makes it clear which changes are breaking and which are extensions.
Also, when you make a change, push a code review to someone ON EACH TEAM. Let them look at how it is likely to affect them, long before they're forced to consume it so that they can implement their own changes on top.
And, when things get really messy; when one team needs to make a change and cannot consume another change easily (this SHOULD be a really rare case), branch the code, make it an entirely different package, but make it a priority to get back onto common code as soon as time allows.
The answer that isn't always as obvious as it could be is to let the teams decide how they're going to share any given component.
For example, my team recently started developing a new product line that shares a lot of code in common with two other teams who have been developing similar products for a long time. Our product is different in a few ways, so we occasionally have to figure out ways to add customization points to the common code.
We've had some clashes about that code, and tried a few different ad hoc ways of dealing with the common ownership. Then with a large new feature coming up, we decided we needed to get all the teams together to get on the same page, which resulted in a smaller group composed of a couple members from each team who are working out the details.
The solution our teams came up with might not work in another situation. You might need something more simple, or something much more formal. The point is, you take collective ownership and figure out what works for you.
I will take liberty to assume:
- acceptance tests are automated..
- component employs good OOP principles: Low Coupling and High Cohesion.
If above assumptions are correct then there should only occasionally be times when two teams would interfere with each other. They can solve it using the following ways:
- As soon as acceptance test of the other team is failed, talk to them to understand if their usage of the shared component is correct or yours. If both usages are fine then see if common part of that usage is pushed up (refactored) to a common base component and variance in usage is managed using child classes or may be via composition.
- Make one person responsible for the component while it is in active development. He should act as a shared resource between the teams.