Why another Article regarding Strategic Domain-Driven Design
There are many books and blogs about Domain-Driven Design. This article will not explain the relevant Domain-Driven Design terms that are already described in many other sources. Instead, it will explain why a good domain architecture can make organizations more efficient and how to achieve effective Strategic Domain-Driven Design in large organizations. I will describe some best practices as well as common mistakes that can lead to misguided solutions.
The correlation between Conway’s Law and Strategic Domain-Driven Design
In his famous Conway’s Law from 1968, Conway described the deep coupling between the communication structure of organizations and the software these organizations design.
Since teams produce software, and the structure of team communication affects the structure of the software, organizations need to be aware that building team structures also impacts the software architecture. This means that decision-makers responsible for structuring organizations are also influencing the (strategic) software architecture of their company. For digital organizations that develop software, it is beneficial to structure teams and their communication in a way that mirrors how the software systems are intended to communicate.
The meaning of Strategic Domain-Driven Design in Organisations
The way teams collaborate and how software systems are designed largely depends on the size of the organization, particularly its digital or IT departments.
In small IT organizations, a few teams manage the entire IT landscape. Typically, this includes CRM and ERP systems, ticketing systems, customer touchpoints (such as shops and apps), and analytics capabilities like data warehouses. In these smaller organizations, a horizontal division of responsibilities is usually the most efficient approach. This means that some specialists focus on developing customer touchpoints, while others maintain and integrate core systems like CRM and ERP. Additionally, another group develops analytics capabilities. Teams generally organize based on their expertise, with separate teams for UI development, backend integration, and analytics.
In larger organizations with many digital capabilities, a horizontal team structure can become problematic and lead to slower team-flows.
Reasons for Vertical Team Designs
There are several reasons why large organizations should consider vertical team structures instead of horizontal ones:
- Communication: Teams often underestimate the effort for communication. When many teams need to interact deeply to deliver customer value, communication overhead increases, which heightens the need for coordination.
- Misunderstandings between teams: When multiple teams collaborate to deliver a customer journey, they must align their integration contracts. This often leads to misunderstandings and repeated iterations before a deliverable can ship to production. For example, a user interface team might wait for backend APIs and start mocking the missing APIs based on previous agreements with the core systems team. When the core systems team begins implementing the API, they may introduce changes based on new insights that emerge after the initial alignment, leading to discrepancies.
- Testing and Debugging: Testing of processes and customer journeys requires involvement from all relevant teams, demanding significant coordination efforts. Debugging can also pose challenges due to the involvement of multiple teams.
- Cognitive Complexity: In a horizontally structured organization, team members typically focus on their technical skills but need to understand a wide range of business processes. This often results in more complex and less structured software solutions.
- Bottleneck Teams: In horizontally structured organizations, certain teams may become bottlenecks. For instance, if a single team of UI engineers develops the frontend of an online shop, they can become overwhelmed as the number of core systems (such as CRM, ERP, billing, campaign management, and identity management) increases. Since only one shop team exists, they can easily become a bottleneck.
Vertical Teams
Small organizations typically don’t need to structure their teams vertically. However, in more complex organizations, teams can operate more efficiently when organized this way. Instead of grouping teams by skills, organizations should design them around meaningful domains.
Each team should include all the necessary skills and roles. Most interactions should occur within the team, while teams should minimize interactions with one another. This design allows teams to deliver independently, without relying on other teams. This is where Strategic Domain-Driven Design comes into play. Organizations can divide a domain into subdomains and multiple bounded contexts, with each bounded context typically owned by a single team.
These teams have all the necessary domain experts and skills to deliver business value directly to the customer. It often makes sense to organize chapters or communities of practice, where experts in a particular skill (such as UI development, analytics, software architecture, requirements engineering, user experience, etc.) can align on standards, share knowledge, and support each other in their specific discipline.
To find the right domain design and corresponding bounded contexts, methods like Event Storming or Domain Storytelling can be helpful.
Each bounded context should have a clear purpose, business value, and scope. It should be distinctly separated from other bounded contexts. Teams should adopt a “share-nothing” approach to avoid dependencies between them. For efficiency, organizations may consider using platforms, which can include technical platforms such as runtime environments, SaaS solutions (inhouse / external), or shared code libraries. However, when deciding to use platforms, the value of sharing resources between teams must outweigh the communication and coordination overhead that this sharing creates.
Common Mistakes on designing Domains
There are common mistakes that teams should avoid. I want to highlight a few:
- Many shared domains: When multiple teams share the same domain, they become tightly coupled. This brings all the disadvantages discussed earlier regarding horizontal team structures, such as high communication overhead, increased coordination efforts, and shared testing and debugging. These factors make both the team structure and the software architecture complex and slow.
- Not having all domain experts in the team: If a team lacks the necessary domain experts, it can slow down significantly. A common mistake is excluding the business side of a domain from the team. Instead of collaborating closely, the business side sees itself more as a stakeholder. This often leads to misunderstandings and unnecessary iterations because business experts only partially engage with the implementation experts.
- Domain experts as members of multiple teams: The cognitive capacity of humans is limited. When domain experts need to participate in multiple teams, they can become stressed and struggle to grasp the different details across various bounded contexts. Attending the rituals of multiple teams consumes time, and missing important team rituals can delay decision-making.
- Bounded contexts without a clear purpose: Each bounded context should have its own clear purpose, meaning it should be designed so that the team can deliver business value directly to the customer. If a bounded context lacks a clear purpose and the team cannot deliver independently, it becomes dependent on other teams to provide customer value (often through processes or customer journeys). This issue frequently arises from tight coupling with other bounded contexts.
- Tight coupling between bounded contexts: Teams should design a bounded context to be loosely coupled with other bounded contexts. This design means that a context primarily listen to business events (which could originate from a customer / user or another bounded context). Based on these events, the bounded context can fulfill its purpose autonomously. It may, in turn, raise new business events that trigger processes in other contexts. However, if two bounded contexts remain tightly coupled, they will need each other – often synchronously – to achieve their goals, creating delays and dependencies.
- Domain logic in touchpoints: A common mistake is implementing domain logic in customer touchpoints. Since microservice frontends can be complex and impact the customer experience, teams sometimes adopt a horizontal approach for building customer touchpoints, especially in apps. However, it’s critical for teams to ensure that all business logic resides within the underlying domains, with no logic implemented in the UI architecture. The underlying domains should deliver autark processes as API’s that can be consumed easaly.
- Cutting Domains Based on Data: When designing domains and bounded contexts, it is important to base them on autonomous processes. Each bounded context is responsible for one or more processes and the necessary domain entities. A common mistake is to consider only data and entities instead of processes during strategic domain design.