Strategic and Tactical Design in Evolving Subdomains: A Comprehensive Guide for Software Architects

Scaibu
6 min readSep 26, 2024

--

As businesses grow and adapt to market demands, their software systems must evolve. This evolution often requires reevaluating and updating design decisions to ensure the software remains scalable, maintainable, and aligned with business objectives. Domain-driven design (DDD) provides a framework for understanding these changes, particularly through subdomains — core, supporting, and generic — and the strategic and tactical design choices that accompany them.

In this comprehensive guide, we’ll explore how the evolution of subdomains impacts software design and how to approach both strategic and tactical design decisions to ensure long-term system adaptability.

The Role of Subdomains in Software Design

In DDD, subdomains represent the business functions that your software serves. These are categorized into three types:

  1. Core Subdomains: The most crucial areas of the business, providing competitive advantages.
  2. Supporting Subdomains: These assist core subdomains but don’t directly differentiate the business.
  3. Generic Subdomains: Routine operations, often similar across various industries.

Each subdomain’s importance shapes how it should be approached in terms of software architecture. However, businesses are constantly evolving, and with them, the strategic importance of subdomains changes, requiring design strategy updates.

Subdomain Evolution: Strategic Impact

A company’s subdomains aren’t static — they evolve in importance over time. Let’s explore how different types of subdomains can shift and how these transitions affect software design.

1. Core to Generic Subdomain

Consider a company, BuyIT, which originally developed its own route optimization algorithm as a competitive edge. Over time, an external service, DeliverIT, offers a more efficient, cost-effective solution. Now, BuyIT’s algorithm shifts from a core subdomain to a generic subdomain, losing its competitive advantage.

For BuyIT, the optimal move is to integrate DeliverIT’s service, reducing internal development efforts. This shift in subdomain importance should guide a corresponding simplification of the software, moving from highly customized internal logic to standardized third-party solutions.

2. Generic to Core Subdomain

On the flip side, BuyIT initially used an off-the-shelf inventory management solution. As business needs grew, the limitations of this generic system led to inefficiencies. BuyIT decided to develop a custom inventory management system tailored to its specific needs, turning this previously generic subdomain into a core subdomain.

A real-world example of this evolution is Amazon Web Services (AWS). What started as a routine infrastructure management task transformed into one of Amazon’s core subdomains, giving it a massive competitive edge.

3. Supporting to Generic Subdomain

Supporting subdomains may also evolve into generic ones. Let’s say BuyIT builds an in-house vendor management system. After some years, an open-source solution is released, offering more features at a lower cost. BuyIT transitions its vendor management from a supporting to a generic subdomain, outsourcing it to the open-source solution and reducing internal maintenance efforts.

4. Supporting to Core Subdomain

A supporting subdomain can also evolve into a core subdomain. For example, if BuyIT enhances its vendor management system to improve negotiations and supplier relationships, this once routine task becomes a significant part of its competitive strategy.

How Subdomain Evolution Affects Software Architecture

As subdomains evolve, the underlying software architecture must also change. This leads to the need for bounded contexts, integration patterns, and decisions around outsourcing or in-house development.

1. Bounded Contexts and Integration Patterns

A bounded context defines the boundary of a subdomain’s logic within the software architecture. As subdomains evolve, these boundaries may need to shift. For instance, when a supporting subdomain transitions to core, the architecture may require more robust integration mechanisms, such as anti-corruption layers, to ensure the core subdomain’s integrity isn’t compromised by external influences.

2. Outsourcing vs. In-House Development

Deciding whether to outsource or keep development in-house is heavily influenced by subdomain importance. Generic subdomains can often be outsourced, while core subdomains should remain in-house to maintain control over business-critical functionality. As subdomains evolve, outsourcing decisions may need to be reevaluated.

Tactical Design Decisions in Software Development

Beyond high-level strategic design decisions, the evolution of subdomains also impacts tactical design. As subdomains shift from generic to core, or from supporting to core, more sophisticated design patterns may be required.

1. Transaction Script to Active Record

In simpler subdomains, developers often start with the transaction script pattern, which is straightforward and directly interacts with the database. However, as business logic becomes more complex, moving to the active record pattern allows for better encapsulation of state and behavior.

Here’s a simple example using C#:

public class Player
{
public Guid Id { get; set; }
public int Points { get; set; }
}

public class ApplyBonus
{
public void Execute(Guid playerId, byte percentage)
{
var player = _repository.Load(playerId);
player.Points *= 1 + percentage / 100.0;
_repository.Save(player);
}
}

As the complexity of business logic grows, transitioning to active record encapsulates state and behavior, making the code easier to maintain and extend:

public class Player
{
public Guid Id { get; private set; }
public int Points { get; private set; }

public void ApplyBonus(int percentage)
{
this.Points *= 1 + percentage / 100.0;
}
}

2. Active Record to Domain Model

As the subdomain evolves, the complexity may require moving to a more advanced pattern like the domain model pattern. In the domain model, complex business rules are abstracted into aggregates and value objects, ensuring consistency and reducing duplication.

3. Domain Model to Event-Sourced Model

For systems that experience a high rate of changes, transitioning from a traditional domain model to event sourcing can provide more flexibility. In this pattern, state changes are captured as a series of domain events, allowing the system to reconstruct the current state by replaying these events. While this adds complexity, it offers high scalability and an audit trail for all state changes.

The Role of Organizational Growth in Design Decisions

As organizations grow, their structure often changes. These changes can directly impact how bounded contexts are defined and how teams interact with them.

For example, if development responsibilities are moved to a different geographical location, the system might shift from a partnership pattern to a customer-supplier relationship. This change in team structure may require redefining the system’s boundaries and adjusting the way teams collaborate.

Importance of Domain Knowledge in Software Design

Domain knowledge tends to erode over time as original developers leave and documentation becomes outdated. Keeping domain knowledge alive is crucial to maintaining a robust and adaptable system. Techniques like EventStorming workshops can help bridge knowledge gaps by involving both developers and domain experts in collaborative modeling sessions.

By continuously refining domain knowledge and aligning it with the evolving subdomains, teams can make informed design decisions that keep the software aligned with business goals.

Strategic Design Considerations

As businesses evolve, software architecture must remain adaptable. Here are a few best practices to ensure long-term scalability and maintainability:

  • Agile Development: Agile methodologies allow teams to iterate and adjust designs as business needs change.
  • Modular Design: By adopting modular design principles, companies can more easily adjust subdomains without impacting the entire system.
  • Continuous Refactoring: Regularly refactoring code ensures the software adapts to evolving business requirements.
  • Collaboration with Stakeholders: Maintaining open lines of communication between developers and business stakeholders ensures the software remains aligned with business goals.

Conclusion

The evolution of subdomains is a natural process in any growing company. Recognizing and accommodating these changes within your software architecture is critical to ensuring scalability and maintainability. By applying strategic and tactical design principles, and continuously reassessing subdomain importance, businesses can build software systems that remain flexible and future-proof.

By keeping a close eye on how subdomains evolve and leveraging both strategic and tactical design decisions, software architects can ensure that their systems grow alongside the businesses they support.

--

--

Scaibu
Scaibu

Written by Scaibu

Revolutionize Education with Scaibu: Improving Tech Education and Building Networks with Investors for a Better Future

No responses yet