Composition May Matter More Than You Imagine
Organizations often underestimate the impact of composition—both in their teams and their software. Yet, time and again, we see how poor composition creates cascading challenges: vague problem definitions, redundant efforts, and tightly coupled systems that are difficult to adapt. The interplay between team and software composition is profound, and Conway’s Law captures this relationship perfectly:
“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.”
Or, as I often paraphrase: Organizations create solutions that are a reflection of their own social structures. Wherever there’s a gap in communication, there will be flaws in the solution. Aligning team structures with business domains isn’t just a leading practice; it’s a foundational step toward creating resilient, adaptable systems. But achieving this requires intentionality in both team dynamics and software design.
Composition
Software Composition
Software composition is the way components are structured and interact. Good composition allows for modularity, clear boundaries, and cohesive responsibilities. Poor composition creates tight coupling, unclear ownership, and systems that break under change.
For example, consider a seemingly minor but pervasive issue with data representation. In one organization, a critical field—“phone number”—was represented uniformly across the database, domain objects, and user interface. Initially, this seemed efficient and straightforward. But when the business needed to adapt, requiring phone numbers to support international formatting and more granular details (like country code and line number), everything broke. The tightly coupled system couldn’t adapt without massive changes across every layer.
This wasn’t just a technical issue; it reflected a failure of composition. A modular system would have introduced a layer to translate between database storage and domain usage, allowing for flexibility without systemic disruption. Instead, the code’s rigidity revealed the organization’s lack of attention to thoughtful boundaries.
This highlights a larger truth: your architecture lives in your code. Many organizations claim to have service-oriented or microservices architectures, yet their systems reveal something different. If services require simultaneous deployments or share hidden dependencies, they function as a distributed monolith. Diagrams and aspirations may paint a modular picture, but the code tells the real story.
Team Composition
Just as poor software composition leads to brittle systems, poor team composition creates inefficiencies and misaligned priorities. Teams that aren’t aligned to business domains often face overlapping responsibilities and delayed feedback loops. The ripple effects can be seen in both team dynamics and software outcomes.
In one case, a lack of consistent terminology across departments created confusion at every level. Sales referred to a “prospect,” while Operations called the same entity a “lead”, and Marketing called them a “contact.” Even the concept of a “policy” was inconsistently defined—departments couldn’t agree on what data a policy contained, what states a policy could be in, and if there were policies with different types or if different types of policies were unique entities. This lack of alignment bled into the software, resulting in convoluted logic. Code was written to translate these differences for various interfaces, and a patchwork of lookup tables emerged to manage these conflicting terms and ideas. Over time, this complexity became a source of frustration and a bottleneck for innovation.
Realigning teams to specific business domains changed everything. By focusing on narrow, well-defined problem spaces, teams were able to reduce dependencies, improve collaboration, and build modular solutions. Instead of designing cross-cutting solutions to satisfy conflicting needs, teams created fit-for-purpose software that better reflected their domain.
Software and Teams Shape Each Other
When work frequently moves across multiple teams before final delivery, feedback loops lengthen, and the ability to respond diminishes. This is particularly evident in organizations structured by functional layers, like separate front-end and back-end teams.
For example, imagine a scenario where the back-end team delivers a set of services according to pre-defined interface contracts. The front-end team begins their work weeks later, only to discover that the services don’t quite meet the intended needs. The back-end team, now focused on new priorities, struggles to revisit old code. Their bandwidth is limited, context has been lost, and the front-end team is left waiting for a fix. The result is frustration, delays, and a final product that reflects these inefficiencies.
In contrast, aligning teams to business domains transforms this dynamic. In one organization, a cross-functional team discovered a flaw in an algorithm for scheduling—a critical issue that had gone unnoticed for years. The team’s domain knowledge, combined with iterative testing and development, allowed them to identify the flaw and propose a solution. This discovery earned the trust of a previously skeptical stakeholder, who became an active participant in brainstorming and problem-solving with the team.
Leading Practices for Better Composition
Improving composition in teams and software requires intentional effort and a willingness to iterate. Here’s how to get started:
Refactor First
Begin with the software. Create clear boundaries, decouple dependencies, and introduce abstractions. These practices help elucidate what your team boundaries might be and make future transitions smoother.Engage Business Partners
Include stakeholders in the change process. Communicate the goal of better collaboration and alignment, and help them transition from static processes to interactive engagement.Iterate on Structure
Accept that you won’t get it right the first time. Share this openly with your teams, and commit to revisiting and adjusting the structure based on feedback.Recognize the Real Architecture
Remember that your architecture lives in the code. Ensure that your systems reflect modularity and independence in practice, not just in diagrams or aspirations.
Conclusion: Evolving Together
Your teams and your software shape one another. By aligning team structures with business domains and embracing thoughtful composition in both code and collaboration, you can create solutions that are resilient, adaptable, and reflective of your organization's true goals. But remember, this is an iterative journey—start where you are, adapt as you learn, and let both your teams and your architecture evolve together.
Further Reading
Related Behaviors
This post ties into several key behaviors from my framework:
Be Meticulous About Composition
Aligning team and software composition ensures modularity and adaptability.Validate Before, During, and After
Shorter feedback loops between teams and domains lead to faster, more reliable validation.Work Together
Collaboration between cross-functional teams and business partners reduces silos and fosters shared understanding.