DDD: Domain-Driven Design

  • The core idea is to put the business domain at the center. We don’t want to structure our app in “technology layers” like database, business, user interface but rather around “business layers”.

Where is DDD Used?

  • used at code level
  • for naming classes, structuring packages, slicing etc
  • also used at system design. very commonly in microservices architectures.

The idea is simple. In microservices we want every service to be totally independent. So the question arises, how to we split our app? What boundaries do we want? One way to answer this is DDD: every bounded context becomes a microservice. By doing this we get that every service has a dedicated business purpose and is “business-wise cohesive”. And every aggregate belongs to exactly one service. This gives us a very nice and focused way of splitting our app. And time has shown that this approach works very well, it’s the most popular approach for splitting a monolith into microservices.

KEY CONCEPT:

→ eg. event storming - building a banking app

  • Domain Events
    • things that can happen in our system, facts that business people care about
    • written in past tense because they already happened
    • money sent, money received, account opened, payment failed, balance updated
  • Commands
    • what commands cause these events?
    • are decisions made by users
    • send money → money sent, open account → account opened, process payment → payment failed (sometimes)
  • Aggregates
    • a cohesive bundle of related events and commands
    • identify things that “belong together”
    • a collection of related objects managed as a single unit with its own lifecycle
    • do this with all the events and commands
    • Account
      • send money
      • receive money
      • have its balance updated
      • be opened or closed
    • transaction agg, payment method agg, regulatory report agg
  • Bounded Contexts
    • a boundary in our big business picture
    • everything in that context is somewhat related, in terms of business
    • ‼️ a bounded context is made up of aggregates as you see, it can be just one or it can be multiple aggregates
      • ❗an aggregate should never be split across different contexts, should be in exactly one context, fully contained
    • Account Management Context:
      • Account aggregate
      • Customer aggregate
    • Payment Processing Context:
      • Transaction aggregate
      • Payment Method aggregate
    • Compliance Context:
      • Audit Log aggregate
      • Regulatory Report aggregate
  • Ubiquitous Language
    • we use one language that both teams understand (dev people and business people)
    • bad (generic)
      class Arrangement {
          String type; // Could be loan, deposit, whatever
          BigDecimal amount;
      }
    • good (domain language)
      class SavingsAccount {
          AccountNumber accountNumber;
          Money balance;
          
          void withdraw(Money amount) {
              if (balance.isLessThan(amount)) {
                  throw new InsufficientFundsException();
              }
              // ... rest of withdrawal logic
          }
      }