Brownfield projects benefit the most from DDD because they already proved their business viability and probably need a way to approach technical debt and design entropy that accumulated over the time.

Strategic Analysis

Best starting point is to invest time in understanding the organization’s business strategy and the current state of its systems’ architecture.

Understand the Business Domain

  1. Identify the company’s business domain.
    • What is the organization’s business domain(s)?
    • Who are its customers?
    • What service, or value does the organization provide to customers?
    • What companies or products is the organization competing with?
  2. Identify the subdomains. Look at the company’s departments/organizational units, how they cooperate.
  3. Identify specific types of subdomains. Focus on the subdomains that are most relevant to the software that you need to work on.

Explore the Current Design

  1. Start with the high-level components. They are not necessarily bounded contexts in the DDD sense, but rather boundaries used to decompose the business domain into subsystems.
  2. Evaluate the tactical design of the high-level components.
    • Which business subdomains it contains?
    • What technical design decisions were taken? What patterns are used to implement the business logic? Component’s architecture?
    • Does the solution fit the complexity of the problem?
    • Can off-the-shelf solution be used?
  3. Evaluate the strategic design.
    • Chart the current design’s context map using the knowledge of the high-level components. Treat them as bounded contexts.
    • Analyze the resultant context map from the DDD perspective. Are suboptimal strategic design decisions? Examples:
      • Multiple teams working on the same high-level component.
      • Duplicate implementations of core subdomains.
      • Implementation of a core subdomain by an outsourced company.
      • Friction because of frequently failing integration.
      • Awkward models spreading from external services and legacy systems.

Look for Lost Domain Knowledge

EventStorming session may be used for this.

Modernization Strategy

Tactical Modernization

Rewriting everything from scratch are rarely successful and more rarely get the support from the management.

Think big but start small - a safer approach to improve the design of the existing system.

Subdomains Boundaries

Logical Boundaries

Start by ensuring that at least logical boundaries (namespace, modules, packages etc.) are aligned with the subdomain’s boundaries:

It’s relatively safe form of refactoring, because we aren’t modifying business logic, just repositioning it in are more well-organized structure.

Physical Boundaries

Look where the most value can be gained by turning the logical boundaries into physical boundaries.

Integration between boundaries

When the minimum required bounded contexts are in place, examine the relationships between them. Analyze how the teams working on them are communicating between each other.

Customer-supplier relationship can be useful for components that were initially design for a partnership relationship, but were it’s no longer sustainable.

Anticorruption layer - for protection of the bounded context from legacy system or from frequent changes in the public interface of an upstream service.

Open-host service - when implementation details of the component ripples through the system and affects consumers.

Separate ways - when it’s easier to let each team to implement their own solutions. Only if it’s not a duplication of core subdomain in question.

Tactical Modernization

  1. Look for the most painful mismatches in business value and implementation strategies. Example: core subdomain with complex logic implemented with transaction script or active record. It needs to change the most often, yet will be painful to maintain and evolve due to poor design.
  2. Decide which business logic implementation pattern best suite what you plan to modernize.
  3. Decide on the modernization strategy:
  4. When refactoring:
    • Small incremental steps are safer than a big rewrite.
    • Changes can be introduced gradually, rather than making atomic changes.
    • Start by looking for possible value objects as immutable objects can significantly reduce the solution’s complexity.
    • When refactoring active records to aggregates analyze transactional boundaries. Do something require Strong consistency but operates on Eventual consistency? Or the opposite: does the solution enforce strong consistency where eventual would suffice?
    • Optionally, protect new codebase from old models using Anticorruption layer.
    • Optionally, protect consumers from changes with Open-host service (OHS) pattern.