Team structure and ownership has a big impact on delivery (from both a quality perspective and velocity perspective) and the architecture of systems and sub-systems. Getting the optimal division of ownership is unfortunately both really important and really difficult to achieve. Worse still there is no fixed formula to make the job any easier. However, it is possible to use principles of IT architecture to help define team ownership in order to achieve a flexible platform which caters to the needs of a growing business.
This is where Conway’s Law comes in; “Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.” Melvin Conway was a clever guy, but what did he mean by this, and why does this happen? If Conway’s Law doesn’t immediately make you think “Golly, that clever chap talks some sense”, then think about this one concept, things generally tend towards the path of least resistance. (If you want to know more about this it’s worth reading Allan Kelly’s post on Conway’s Law v. Software Architecture). The key component of Conway’s Law is the very last bit, “communication structure”, if the communication structure, doesn’t mirror the architecture you would ideally like to achieve, then getting to this vision is likely to be very difficult. The key problem areas tend to be teams owning more than they should, teams not having any ownership of the code they delivery, or multiple teams owning different components in the same domain.
Owning too many different domains
Take for example a scenario where 1 team owns 2 different services, ‘Service A’ needs to get the result of a very complex calculation which occurs in a very similar way, but for an entirely different context in ‘Service B’. When this type of scenario comes up, most of the time, the right development approach is taken. But, generally over the longer term, the path of least resistance prevails and if the wrong approach is taken ‘once’ for the implementation in ‘Service A’. The calculation in Service B ends up being modified and reused when it shouldn’t. That ‘once’ is enough to set the precedent for the future between these 2 services. This may sound trivial, but over time, these 2 services start to become coupled. If you’re a developer, when was the last time you thought “I know where I can get that data from” without taking a step back and thinking, “Do I really want these 2 things to end up dependant on each other?”. Every business is trying to deliver value, the focus on visible business value often makes it too easy to fall back to the path of least resistance.
IMPACT: Abstraction and encapsulation is easily broken thus changes become risky as they can impact other domains.
Imagine a scenario in a very large organisation where individual teams don’t have any independent ownership of different parts of the system. Because of the size of the organisation, the number of teams and the amount of work it’s difficult to keep up to date with what all teams are doing. The development team is selected for a project based on availability/team capacity. Assume there are 2 separate teams working on 2 separate projects (not necessarily at the same time). The requirements for both project are pretty much the same except one project takes some requirements further. It’s too easy for the same capability to be built twice in 2 different ways purely because it was too difficult to know everything that is going on.
IMPACT: Remember, code is a liability, functionality is an asset. This scenario is a breading ground for bad code and a ‘Project Orientated Architecture’ that creates inflexibility (read my previous post for more information).
Interdependent ownership of a domain
If 2 teams are having to work together for everything they do, logically they are a single delivery team. But because these teams work separately, have different priorities and have a different backlog of work, a lot of effort in delivering value is lost to updating, consulting, approving, showcasing etc. That’s not to say inter-team communication is bad, it’s good, and it’s required. Generally good communication across 2 teams can be efficient but it’s not necessarily effective. These 2 teams are likely to end up frustrated with each other, the delivery of one team is coupled to the delivery of another. As the teams are separate, there is an overhead for the communication requirements between the 2 teams. In a lot of cases it’s easier for the teams to implement local optimisation, e.g. implementing a function/method in ‘Service A’ when it should be wholly owned by ‘Service B’. If however, the ownership was within 1 team for both services, then this overhead doesn’t exist because the dependency doesn’t exist. Given the teams are continually trying to deliver, they are effectively incentivized to ‘get the job done’, the path of least resistance prevails.
IMPACT: Abstraction and encapsulation is easily broken.
Just a communication issue?
Now some may say that the last 2 scenarios are just communication issues and that good developers communicate well, and yes they do. However, the larger an organisation is the harder it is for every team to be aware of what all the other teams are doing. Most people agree that it’s really valuable if all teams know what all other teams are doing, but there is a trade-off. Relying on everyone to appreciate all the changes across the business isn’t scalable. This can easily become a full time job for one or more people (in some cases there is even a team of people who are responsible for making sure that changes to the system are documented).
Remember Conway’s Law, in the first case the 2 services will begin to fuse over time. For the second case, the lack of ownership doesn’t hinders the development teams to deliver long-term benefit alongside short-term business priorities, the system as a whole can easily end up tightly coupled. In the third case, the sub-optimised communication between teams ends up becoming apparent in the architecture we end up with duplication where it really could be prevented and tight coupling. In all cases; the effort involved to deliver value is greater than should be required; and the system architecture is suffering because of the communication structure.
How using Conway’s Law can help
Luckily, you can use Conway’s Law to your advantage by defining teams along lines of capabilities which should be independent from other lines of capabilities. This creates abstraction without it being dictated as part of each project. Assuming you know what your system architecture should look like, and that domain boundaries are clear in this vision, giving independent ownership of whole domains allows each team deliver their work without having to rely on other teams. If work has to cross a domain boundary then there is a chance that the boundaries of ownership may not be optimal. Having teams ‘own’ independent domains and all the services/components of that domain allows them to have a vision on where that part of the system should go, and therefore, allows them to ensure that any good work they do can have a long-term impact. Independent ownership sets an expectation that the team will have to live with the code they deliver and, the team doesn’t have to worry that someone else will ‘screw up’ their domain. Broken Glass Syndrome can be tackled as the teams are empowered to make improvements over time. The team is incentivized to make small incremental improvements to reducing long-term effort.
Scaling this approach out so that all teams independently own different domains of the system allows each domain to become more independent. Independent domains mean that a change in one part of the system is unlikely to affect another part of the system. The right macro and micro architectural implementation ends up being the “path of least resistance” if development teams have independent ownership of well defined domains with clear separations of concern.