Domain-Driven Design Distilled

Design is inevitable. The alternative to good design is bad design, not no design at all.

Strategic Design

  • Bounded Context is a semantic contextual boundary.

Bounded Context

  • This means that within the boundary each component of the software model has a specific meaning and does specific things. A bounded context is where a model is implemented, and you will have separate software artifacts for each bounded context.
  • The software model inside of the context reflects a language that is developed by the team working on the context and is spoken by every team member. It is called Ubiquitous Language and it is spoken among the team members and implemented in the software model. Because of that, it must be strict, exact, stringent and tight.
  • When the bounded context is being developed as a key strategic initiative of your organization, it is called Core Domain.
  • There should be one team assigned to work on one bounded context. There should be also a separate source code repository for each context.

Core Domain

Domain Experts and Business Drivers

  • Projects are organized according to business drivers and under an area of expertise. You need to think of division or function in those teams.
  • Different languages means differences must be segregated into different bounded contexts.

Fundamental Strategic Design

  • Employing a bounded context forces us to answer the question: “What is core?”. The bounded context should hold closely all concepts that are core to the initiative and push out all others.
  • How do we know what is core? We have to bring together Domain Experts and Software Developers. It is based on the expertise of the Domain Experts that we begin to form the foundation of the ubiquitous language.

Focus on Business Complexity, Not Technical Complexity

Developing an Ubiquitous Language

  • Do not limit your Core Domain to nouns alone. Consider expressing it as a set of concrete scenarios about what the domain model should do, in terms of what its components do.
  • Scenarios can then be transformed into artifacts called Specification By Example, also known as Behavior-Driven Development (BDD). By creating Acceptance Tests, you can validate your domain model against the team specifications.

Architecture

  • The Domain Model should be free of technology. For one thing, transactions are managed by the application services and not by the domain model.
  • DDD can be used with any of them, architectures or architectures patterns, mixing and matching as needed:
    • Event-Driven architecture; Event Sourcing
    • Command Query Responsibility Segregation (CQRS)
    • Reactive and Actor Model
    • REST
    • Service Oriented Architecture (SOA)
    • Microservices

Strategic Design with Subdomains

  • One bounded context will be the Core Domain and the other Subdomains (ideally).
  • A Subdomain is a sub-part of your business domain. Another way to think about it is that it is a clear area of expertise. assuming that it is responsible for providing a solution to a core area of your business.

Types of Subdomain

  • Core Domain: this is your specialty. DDD belongs to it.
  • Supporting Subdomain: this is a modeling situation that calls for custom development, but not as much as the Core Domain in terms of investment.
  • Generic Subdomain: this is a solution that may be purchased off the self but also outsourced or developed by a less talented team.

Dealing with Complexity

  • To reason about legacy systems, use Subdomains as a tool for discussing your problem space.
  • When using DDD, a Bounded Context should align 1:1 with a single domain. If you must create a second model in the same Bounded Context (within your Core Domain), you should segregate the secondary model into a separate Module (a package in Scala/Java, and a namespace in F#/C#, for example).

Strategic Design with Context Mapping

  • The Core Domain will integrate with other Bounded Contexts through Context Mapping.
    • It represents the translation between two ubiquitous languages.

Context Mapping

  • What relationships and integrations can be represented by the context mapping line?
    • Partnerships: a relationship between two teams, each with its own bounded context.
    • Shared Kernel: one or more teams share a small but common model.
    • Customer-Supplier: upstream and downstream services. The supplier usually works to provide the customer needs.
    • Anticorruption Layer: it is a defensive relationship, where the downstream team creates a translation between the ubiquitous languages, isolating the downstream model from the upstream one.
    • Open Host Service
    • Published Language: it is a well-documented information exchange language enabling simple consumption and translation by any number of consuming bounded contexts.

Domain Events

  • A domain event is something that happened in the domain that you want other parts of the same domain (in-process) to be aware of.

Tactical Design with Aggregates

  • What is:
    • Entity: it models an individual thing. It has an unique identity which distinguishes it from other entities of the same or a different type.
    • Aggregate: it is composed of one or more entities, and may contain Value Objects.
    • Value Object: models an immutable conceptual whole.
    • Root Entity: owns all other elements inside of an aggregate.
  • Each aggregate forms a transactional consistency boundary.
    • Only one aggregate may be committed and modified in a single transaction.

Aggregates

Rules of Thumb

  1. Protect business invariants inside aggregate boundaries.
  2. Design small aggregates.
  3. Reference other aggregates by identity only.
  4. Update other aggregates using eventual consistency.

Modelling Aggregates

  • Avoid the Anemic Domain Model, where the aggregates have only public accessors (getters and setters) but no business behavior (this is applicable only to OOP).
  • Use immutable Value Objects.
  • Choose your abstractions carefully.
  • Right-sizing aggregates
    1. Design small aggregates.
    2. Protect business invariants inside aggregate boundaries.
    3. Evaluate how much time may elapse until each of the reaction-based updates may take place.
  • Update other aggregates using eventual consistency.
  • Design for testability.

Tactical Design with Domain Events

Designing, Implementing and Using Domain Events

  • Every Domain Event should implement this minimal interface:
interface DomainEvent {
  Date occurredOn;
}
  • The Domain Event type should be named carefully and reflect your model’s Ubiquitous Language.
    • They should be a statement of a past occurrence, i.e. a verb in the past tense.
  • All properties that convey a record of what happened in the Domain Model should be contained on the Domain Event.

Event Sourcing

  • It can be described as persisting all Domain Events that have occurred for an Aggregate instance as a record of what changed about that Aggregate instance. Rather than storing the state as a whole, you store all Domain Events that have happened to it.
  • All of the Domain Events that have occurred for one Aggregate Instance, ordered as they originally occurred, make up for its event stream.

Acceleration and Management Tools

  • Timelines exist and will affect your outcomes. Service design is inevitable; design must be made in an accelerated way, delivering the very best design possible within the time limits that you face.

Event Storming

  • Domain Experts and Developers get engaged into a fast-paced learning process. Its focus lies on business and its processes.
  • You need a pad of sticky notes and a pen for each participant. A whiteboard and a roll of craft paper will also be needed.
  • Follow the steps:
    1. Create Domain Events to emphasize the business processes. Write the name of each event on a note. Place the events from the left ot the right, as in a timeline. When in doubt, drop it somewhere else. Use vertical spacing to position parallel events. Mark trouble spots with a note and some text.
    2. Create the Commands that cause each Domain Event. On a sticky note, write the name of a Command that causes a certain event. Commands/Events should be associated in pairs.
    3. Associate the Entity/Aggregate on which the Command is executed and that produces the Domain Event outcome. Write the name of the Aggregate (or Data) on a note and place it near/alone the Command/Event pair. The same Aggregate may be created on multiple pairs.
    4. Draw boundaries and lines with arrows to show flow on your modelling surface. Use solid lines for Bounded Contexts and dashed lines for Subdomains. Draw lines with arrowheads to show the direction of Domain Events flowing between Bounded Contexts.
    5. Identify the various views that your users will need to carry out their actions, and important roles for various users.