Skip to content

Instantly share code, notes, and snippets.

@iamsmkr
Last active March 20, 2024 22:00
Show Gist options
  • Save iamsmkr/1e3a8293f00eb54676b977f649ba7b86 to your computer and use it in GitHub Desktop.
Save iamsmkr/1e3a8293f00eb54676b977f649ba7b86 to your computer and use it in GitHub Desktop.
Reactive Architecture: Domain Driven Design Course Notes

Domain Driven Design

What is a Domain?

  • A domain is a sphere of knowlege.
  • In the context of software, it refers to the business or idea that we are modeling.
  • Experts in the domain are people who understand the business, not necessarily the software.
  • Key goal of DDD is to build a model that the domain experts understand.
  • The model is not the software.
    • The model represents our understanding of the domain.
    • The software is an implementation of the model.

Ubiquitous Language

  • Communication between developers and domain expert requires a command language. This comman language is called as the Ubiquitous Language.
  • Terminologies in the Ubiquitous Language comes from the domain experts.
    • Words originate in the domain and are used in the software.
    • Avoid taking software terms and introducing them into the domain.
  • Domain experts and software developers should be able to have a conversation without resorting to software terms.

Decomposing The Domain

Large Domains

  • Business Domains are often large and complicated
  • They contain many ideas, actions, and rules that interact in complex ways.
  • Trying to model a large domain can become problematic.

Subdomains

  • Large domains may be separated into subdomains.
  • Subdomains are created by grouping related ideas, actions and rules.
  • Some concepts may exist in multiple subdomains:
    • Shared concepts may not be identical initially
    • They may also evolve differently
    • Avoid the temptation to abstract

Bounded Contexts

  • Each subdomain has its own ubiquitous language and model.
  • The language and model for a subdomain is called a Bounded Context.
  • Subdomains and Bounded Contexts are good starting points for building Reactive Microservices.
  • From one Bounded Context to the next, the meaning of a word may change dramatically:
    • In a restaurant, when talking to a server, an Order has a very specific meaning.
    • When speaking to the person who manages inventory for the restaurant Order means something completely different.
  • We also need to observe how the details of the model change:
    • In a restaurant, when the kitchen is preparing an Order they don't care about prices.
    • When a customer pays for the Order, price is critical.
    • It is the same Order but the relevant details of that Order change.

How to determine Bounded Contexts?

  • No universal answer, but there are some guidelines:
    • Consider human culture and interaction.
      • Different areas of the domain that are handled by different groups of people, suggests a natural division.
    • Look for changes in Ubiquitous language.
      • If the use of language or the meaning of that language changes, that may suggest a new context.
    • Look for varying or unnecessary information.
      • Employee Id is very important in an employee, meaningless in a Customer.
    • Strongly separated bounded contexts will result in smooth workflows.
      • An awkward workflow may signal a misunderstanding of the domain.
      • If a bounded context has too many dependencies it may be overcomplicated.

Event-First Domain Driven Design or Event storming

  • Traditionally, DDD focused on the objects within the domain. Eg. Cook, Reservation, Customer, etc.
  • Event-First DDD places the focus on the activities or events that occur in the domain. Eg. Customer makes a reservation, Server places an order, Food is served to the customer.
  • Using Event-First DDD we start by defining the activities, then group those activities to find logical system boundaries.
  • Service-Verb-Object approach could help you identify elements in an event.
  • Give preference to direct objects over indirect objects.

Maintaining Purity

Anti-Corruption Layer

  • Each Bounded Context may have domain concepts that are unique.
  • Concepts are not always compatible from one context to the next.
  • Anti-Corruption Layers are introduced to translate these concepts.
  • An Anti-Corruption Layer will prevent Bounded Contexts from leaking into each other.
  • Anti-Corruption Layer help the Bounded Context to stand alone.
  • When it comes to dealing with a legacy systems whose domain may be messy or unclear, ACL may be implemented in the Legacy System, or in the Bounded Context or both.

Context Maps

  • Context Maps are a way of visualizing Bounded Contexts and the relationships between them.
  • Bounded Context are drawn as simple shapes.
  • Lines connect the Bounded Contexts indicate relationships.
  • Lines may be labelled to indicate the nature of the relationship.

Domain Building Blocks

Domain Activities

  • Command, Events & Queries are the messages in the Reactive System.
  • They form the API for a Bounded Context or a Microservice.

Commands

  • Request to perform an action which could be rejected.
  • Causes change in the domain state.
  • Usually delivered to a specific destination.

Events

  • Represents an action that happened in the past.
  • Since the action is already completed, it cannot be rejected.
  • Records change in the domain state.
  • An event can be broadcasted to many destinations within a system.

Queries

  • Represents a request for information about the domain.
  • Queries should never alter the state of the domain.
  • Usually delivered to a specific destination.

Domain objects

Value objects

  • Value objects are defined by its attributes
  • Two value objects are equivalent only if their attributes are same
  • Value objects are immutables
Address(Number: 123, Street: Play street, City: Lagomville, State: Akkansas, Country: Lightbendia) ==
Address(Number: 123, Street: Play street, City: Lagomville, State: Akkansas, Country: Lightbendia) !=
Address(Number: 123, Street: Reactive lane, City: Lagomville, State: Akkansas, Country: Lightbendia)
  • In addition to state, value objects can contain business logic
  • Messages in Reactive Systems are implemented as Value Objects

Entities

  • An Entity is defined by a unique identity i.e., an id or a key
  • An Entity may change its attributes, but not its identity
  • If the identity changes, it is a new entity, regardless of its attributes
  • Entities are single source of truth for a particular id
Person(Name: John Smith; Height: 5'11'', Weight: 185 lbs, Hair Color: Brown, Eye Color: Blue) ==
Person(Name: John Smith; Height: 5'11'', Weight: 175 lbs, Hair Color: Red, Eye Color: Blue) != 
Person(Name: Jane Smith; Height: 5'11'', Weight: 175 lbs, Hair Color: Red, Eye Color: Blue)			
  • Entities can also contain business logic
  • Actors in Akka are excellent model for entities. They have unique id in the form of address. Their state is mutable. Actors in Lagom are called as Entities as in DDD.

Aggregates

  • An Aggregate is a collection of domain objects bound to a root Entity
Person -> Name
Person -> Address
Person -> Phone Number
  • The root Entity is called the Aggregate Root
  • Objects in an Aggregate can be treated as a single unit
  • Access to objects in the Aggregate must go through the Aggregate Root
  • Transactions should not span multiple Aggregate Roots
  • Aggregates are good candidates for distribution in a Reactive System
  • The aggregate root can be different from one context to the next
  • Some contexts may require multiple aggregate roots
  • Some questions to consider while determining the aggregate roots:
    • Is the entity involved in most operations in that bounded context? Yes
    • If you delete the entity, does it require you to delete other entities? Yes
    • Will a single transaction span multiple entities? No

Domain Abstractions

Services

  • Business logic doesn't always fit with an entity or value object. Such logic can be encapsulated by a Service.
  • A Service should have stateless business processing logic.
  • Often used to abstract away an anti-corruption layer.
  • Too many services lead to an anaemic domain. Look for a missing domain object before resorting to a service.

Factories

  • Logic to construct new domain objects may not be trivial. May require access to external resources like databases, files, REST APIs, etc.
  • Factories abstract away the logic of creation.
  • Usually implemented as a domain interface, with one or more concrete implementations.

Repositories

  • Repositories abstract away the retrieving of existing objects.
  • Factories are used to get new objects, Repositories are used to get, or modify existing objects.
  • Often operate as abstraction layer over databases, but they can work with files, REST APIs etc. A repository does not automatically imply a database.
  • Factories and Repositories are related. For this reason, they are often combined. A Repository may end up with all of the Create, Read, Update, Delete operations.
  • Tools like Akka and Lagom are powerful because they provide facilities that abstract away the need for Repositories. Implementation of Repositories in Akka or Lagom is done through plugins.

Notes:

  • OrderDTO (A Data Transfer Object which is serialized into JSON to be exposed by a REST API)
  • OrderDBO (A Object/Relational Mapping. Maps database tables to classes/fields.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment