TL; DR: When different parts of an organization need to coordinate, it seems like a good idea to help them coordinate smoothly and frequently. Don’t. Help them coordinate less — more specifically, less often.
Software systems become large, they have many parts, and those parts need to talk to each other. Maybe we’re building a new customer portal, and the new web service needs to talk to existing customer relationship management (CRM), warehouse systems for returns, and invoices. The software cuts across organizational boundaries.
If software is going to talk to each other, teams need to talk to each other. The new service requires changing new apis from the warehouse and billing. Maybe there is some customization in CRM as well. All this needs to be coordinated.
How can we make this coordination easier? (That seems like the question to ask.)
I know, let’s move all the departments to the same tracking tool! Everyone will use JIRA. This way, we can roll all changes into one place, where warehousing, invoicing, and the new customer portal team can all see each other’s status.
This visibility allows us to couple more deeply. Now we have dependencies between individual tasks in completely different departments. Now everyone needs to keep up with everyone. So many project managers are busy keeping track of everything! Each task affects people throughout the company.
Within departments, teams have basic coupling between the software systems they write. Enabling task-level coordination creates coupling on individual work items within the team. So much coordination! So many handoffs!
By making coordination easier, we can achieve more coordination. This leads to some optimizations, such as: if we wait until the service is complete to write the call to the repository, the portal team can do less coding. Then, CRM changes can wait for us to change, and our changes wait for something else — the coordination effort swells.
But coordination is not what we want to do! We want to build software. What we want to do is build software.
Try this: Instead of making coordination easier, imagine it’s really expensive. How are we going to do less?
To minimize coordination, establish boundaries and a small number of interfaces across boundaries. Work carefully on these interfaces: document them thoroughly, and test them on both sides. Change as little as possible, change as hard as possible: versioning, backward compatibility, phase out.
Instead of asking when the other side of the border will be ready, assume we don’t know. Write contract tests, translation layers, and custom dummy tests.
Treat another department like another company, like software as a service, and we can’t control their schedules. We can’t access their tracking tools there.
There is a lot of communication around the content of the interface. And nowhere else. This leaves departments to work separately.
A strong boundary is like an extra component. It requires more work, but that work stays within the department, not across it. No entanglements at the task level. Each team works at its own pace.
While some production releases may wait for all components to be delivered, no component development waits for each other. This makes this faster than highly coordinated, tightly coupled releases. When difficulty increases with size (as in software systems), several small systems can work more efficiently than one large one.
This decoupling requires more work on the software.
It’s faster, but is it cheaper? It takes more work: writing tests and artifacts, building ports and adapters, and changing those adapters when our first guess about the interface turns out to be wrong. This requires more build software.
This is not what we want to do! We want to build software — oh, wait.
The extra work of clarifying boundaries makes the software better.
The extra work of coordination just makes it take more time.
When we change the system later, strong boundaries make those changes faster. Deep coordination makes these changes harder: tight coupling still exists, but the army of project managers who heroically put the initial release together has moved on.
This coordination is also very expensive. More managers. In addition, it is expensive (and unhappy) for software developers to sit on coordination phones, test hard, and wait for dependencies.
Making coordination smoother increases coupling and requires more coordination. Another option is to spend development efforts at healthy boundaries. You can pay for better coordination, or better software.