My Book Notes: Domain Driven Design (The Blue Book)

ismail bayram
7 min readApr 24, 2023

--

Book Review

Firstly, thank you for this great master of piece to Eric Evans. It was a comprehensive guide to build and maintain software projects. I’ve read 80% of book (skipped the part III. only it tells stories), Unfortunately it is a disappointing for me. The style of book is like a turtle, it brings you to somewhere important but very slowly. Also you can find key informations on the internet, I think it is not worth to read it.

Focuses at the beginning of this book;

  1. For most software projects, the primary focus should be on the domain and domain logic.
  2. Complex domain designs should be based on a model.

I. Putting the Domain Model to Work

A domain model is not a diagram. It is the idea that conveys the rules of the business.

Utility of Model in DDD

The model is the backbone of a language that used by all team members.

Ingredients of Effective Modelling

  1. Binding the model and the implementation.
  2. Cultivating a language based on the model.
  3. Developing a knowledge-rich model.
  4. Distilling the model.
  5. Brainstorming and experimenting.

Use of Common Language

A project may fail when the developers and domain experts started to talking about the project using different terms. A project needs a common language for all team members which include developers, pms, domain experts and also stakeholders. This is Ubiquitous Language.

Summary of Part I

  • Create a Ubiquitous Language on your team for all members and use it directly when communicating
  • Always model your business invariants and scenarios and make them up to date.

Beyond two items above, there is no additional useful information; the rest are merely stories.

II. The Building Blocks of a Model-Driven Design

Isolating the domain layer implementation is a prerequisite for domain-driven design.

Entity(aka Reference Object)

An object that represents continuous state through the different states even or different implementations. An entity object has a unique identity for distinguish it from the same types of it.

Value Object

It is an attribute that describes the state of something. Value objects describes the things, not define them. Value objects can reference entity objects. For instance, a route from A point to B point is a value object but it holds the references both of Point A and Point B.

  • Value objects should be immutable.
  • They might be passed as parameter or message to anything.
  • They convey the data and be discarded.
  • Gain of immutability is passing Value object to other objects and knowing it is not changed.

When to Allow Mutability

  • If the Value Object changes frequently
  • If changing an attribute of a Value object or creating a new one is expensive in terms of memory.

Tuning a Database with Value Objects

If a row holds a reference of another object which is on the different page or in the different cluster, referenced object can be stored as a value in the row as a value object. This technique is called denormalization such as in NoSQL databases.

Services

Some operations do not fit in the objects like Value object or Entity. They contain activities or actions, we call them Services. Though, but we try to fit them into objects anyway.

  • Services do not hold state, they manage relationship with other objects.
  • Service names come from Ubiquitous Language.
  • Services do operations that are not a natural part of an Entity or Value Object.

Application Services vs Domain Services: For example; if we extract a report from a bank account, the operation is in the application service. On the other hand; if we transfer between accounts, the operation is in the domain service.

Modules (aka Package)

Like everything in Domain-Driven Design Modules are a communications mechanism. If your model tells a story, you Modules are chapters.

  • Module names should be given as part of the Ubiquitous Language.
  • Modules should be low coupled and highly cohesive.

Aggregates

An Aggregate is a cluster of associated objects that we treat as a unit for purpose of data changes. Each Aggregate has a root and boundary. The boundary defines what is inside the Aggregate. The root is a single, specific Entity contained in the Aggregate. The root is the only object that outside objects allowed to hold reference to.

For example, let a car be an Aggregate. Its tiers are entities which have unique identities in the car. But outside of the car, identities of the tiers are not important. Thus in this example, the root Entity of the car is itself.

  • Root entities have global identity.
  • Entities inside the boundary have local identity, unique for only within the Aggregate.
  • Nothing outside of the Aggregate hold the references of inner objects such as tiers, engine etc.
  • Only Aggregate roots can be obtained directly with db queries. All other objects must be found by traversal of associations.
  • Objects within the Aggregate can hold references to other Aggregate roots.

Factories

Creating an object might require complex operations within the client which should not be dirty. Thus we should create objects which are responsible for creating Aggregates. These are Factories.

  • They are not part of the domain layer.
  • Factory creation must be an atomic operation that guarantees all invariants of the object be satisfied.
  • Factory is a logical place to keep invariants for creating objects. Factories should validate the object invariants when creating.
  • A factory encapsulates life-cycle transition, creation and reconstitution of objects.

Reconstitution of Objects

A Factory creates objects with parameters and checks the violation rules for its invariants. But if the object restores from the database, it should know that fact and it does not have to check the violation rules.

Repositories

Accessing directly storage engines from domain layer muddles the objects such as entities, aggregates and violates the encapsulation. Repositories are the interface of data stores for clients.

  • Only Aggregates should access the Repositories.
  • They decouple obtaining objects from persistent storage from the application.
  • They can be mocked in unit tests.

Factories make new objects, Repositories find old objects.

III. Refactoring Toward Deeper Insight

Do small refactorings. After many of them, you can reach the supple design, don’t be hurry.

… So many stories about refactorings and references to some of Fowler’s tecniques.

IV. Strategic Design

Bounded Context

We can assume that Bounded Contexts are Cells in our bodies which are allow what can get in or out.

  • Explicitly set boundaries in terms of team organisation.
  • Bounded Contexts are not MODULES.

A bounded context defines a clear boundary within which a specific domain model is defined and applied. It is a context in which the ubiquitous language used to describe the domain is well-defined and understood by all stakeholders, including developers, business analysts, and domain experts.

Context Map

Identifying and drawing Bounded Contexts is Context Map. This graphs defines team responsibilities.

Anti Corruption Layer

Anti-corruption Layer (ACL) is a pattern that aims to protect a new system from the complexity and inconsistencies of an external system. It’s a layer of code that isolates the new system from the legacy system and ensures that the new system’s domain model remains pure and untainted by the legacy system’s terminology and concepts. The ACL translates the legacy system’s messages and data into a form that is compatible with the new system’s domain model. The main goal of the ACL is to maintain the integrity of the new system’s domain model and to avoid contaminating it with the legacy system’s concepts.

Conformist

Conformist, on the other hand, is a pattern that aims to integrate two different domains by adapting one domain’s model to conform to the other domain’s model. Unlike ACL, Conformist does not isolate the new system from the legacy system. Instead, it adapts the legacy system’s domain model to conform to the new system’s domain model. Conformist can be used when the legacy system’s model is outdated, inconsistent, or incompatible with the new system’s model. The main goal of Conformist is to enable communication and collaboration between two different domains by creating a common language and a shared understanding of the domain.

Shared Kernel

A shared kernel is a pattern that describes how to share a common subset of a domain model between two or more bounded contexts. The shared kernel pattern allows different parts of an organization to use the same language and concepts to solve common problems, while still maintaining their own domain models. The shared kernel pattern is a way to share a common subset of a domain model between multiple bounded contexts or applications. It can provide benefits in terms of code reuse and consistency, but also comes with challenges related to change management and coordination between teams.

--

--