View More

The first pattern of domain driven design (DDD) I would like to take a closer look at is the “Entity” tactical design pattern. We all know the term “entity” and may have a certain picture in our mind when we read it. I was first introduced to it while learning about entity relationship diagrams that are used to design databases. However, in DDD an entity is an element of the domain model, a kind of domain object.

The domain model entity element has distinct characteristics which separate it from value objects, another pattern that DDD uses to model domain objects. The main differences are that entities have an identity which stays the same during their lifecycle and that they are mutable whereas value objects are immutable.

The Pattern

An entity is a domain model element that represents some domain object. It has attributes and methods. For example, a ship that has a certain name and capacity.

One of the main characteristics of an entity is that it has an identity. The identity never changes through the life cycle of an entity. An example of this is a person who has a certain name. When the name changes if that person is married for example, the identity has to be preserved.

When comparing entities with each other, we cannot rely on their attributes. Two person objects with the same name value don’t necessarily have to represent the same Person. On the other hand, consider a contact detail object with an attribute phone number. This object doesn’t have an identity on its own, every contact detail object with the same phone number could replace it with no change in meaning.

Entities have a life cycle which starts when they are created. They can be loaded from a persistence store, changed due to an event or action and then stored to persistence again. At the end of their lifecycle, they are destroyed. For example, a car is built which starts its lifecycle. Then after some years in use, some parts are replaced. Finally, when we take the car to the scrap yard where they dismantle it, its lifecycle ends.

Commands and Queries

Methods of entities are either commands or queries. Commands are used to change the state of the entity, for example set an attribute to a new value. They never return state. In contrast, query methods should never change the state of an entity but return some value.

This distinction makes it easier to reason about our code. We know that a query method doesn’t change anything. When calling a command, we know that we may better carefully inspect what it does exactly.

Validation of invariants

The entity pattern advises us to model the invariants of an entity. Invariants are facts or rules that are always true after a command made a change to an entity. For example, a car needs to have always exactly four wheels. So after the command that changes the wheel of a car, we need to check this invariant.

Therefore after each command or series of commands that we execute on the entity we need to validate it. Even when factories create new entities, they should be in a valid state from the beginning of their life cycle.

Associations

Eric Evans also discusses associations in his DDD book [Eva04]. Many associations are bi-directional in nature, and therefore we model them as such initially. If we translate those directly into the software, the model becomes very entangled and hard to maintain. Therefore we should strive to minimize associations within the model and code.

Three ways to reduce associations are imposing a traversal direction, reducing multiplicity by introducing a qualifier and removing the association altogether. The following sections describe a sample of each possibility.

Impose direction

Imagine my favorite sample of the webshop. There are baskets to which users add products. The association between baskets and products is many-to-many. Does this imply that we need to maintain a list of baskets inside the product entity?

Most of the time it should suffice to be able to query the basket for its products. A product doesn’t have to know in which baskets it is stored. That’s a question the application may never need to answer. If it does, we can query the repository (database) for the answer.

If we needed to maintain both directions within the model, every addition of a product to the basket would need another operation that adds the basket to the list of baskets of the product. By imposing the direction, we can simplify the code.

Reducing Multiplicity

The following diagram shows the association between student and subject. It is a many-to-many association because students study multiple subjects and subjects are studied by multiple students.

To reduce the multiplicity we could, for example, add time slots to the model. At a given timeslot a student can only study one subject. Therefore the multiplicity is reduced to one-to-many.
This association is much easier to maintain in the code of the model.

Removing associations

The ultimate simplification is removing associations altogether. When the association is purely informative for example, or when it is used only in a given context we may better remove it. For example, the application for a publishing company may records reviewers of a book during the publishing process. However, once the book is printed and added to the store of the company, there is no need for the association to the reviewers anymore.

Wrap Up / Final Thoughts

The entity pattern defines domain entities which can be modeled and translated to code. It divides methods into commands and queries with clearly defined semantics. Entities maintain a lifecycle, and we can minimize their associations in multiple ways.

The next pattern in the series will be value objects. Generally, they should be preferred over entities when modeling. Let’s see why in the next post.

[Eva04] Eric Evans: Domain-Driven Design – Tackling Complexity in the Heart of Software (homepage)

View More

Welcome to this blog post series about concepts and patterns of domain driven design (DDD). Although the original book about DDD [Eva04] was written almost 15 years ago, I only recently stumbled upon an article about it on the internet [Sch17]. This read drove my interest in DDD, and I started to dig deeper, read the original book, watched some conference recordings and started to experiment.

In my opinion, DDD captures the common sense of software design and makes it explicit. I’ve seen many advanced software engineers implement the concepts and patterns of DDD which have never heard of Eric Evans and his book. That’s why I would like help to spread the word and write this series.

This posts shall give an overview of what DDD is all about. The further posts of the series will dig deeper into the concepts and patterns.

Introduction to DDD

Eric Evans does a great job defining DDD at his keynote speech at the explore DDD 2017 conference. I highly recommend you watch it. On the first slide he defines four fundamental concepts of DDD as follows:

  • Focus on the core complexity and opportunity in the domain
  • Explore models in a collaboration of domain experts and software experts
  • Write software that expresses those models explicitly
  • Speak a ubiquitous language within a bounded context

The first point is about putting the domain in the center of software and focus on it. Everything else should be built around the domain and may be replaced without affecting the core functionality. Different people have different names for an architecture like this for example “Clean Architecture”, “Onion Architecture” or “Hexagonal Architecture”. The core idea is always the same: Use dependency inversion to put the domain at the center.

The second point is about requirements and how we best gather them. It states that we should explore the models with domain experts. This advice aligns nicely with agile methodologies that recommend close interaction with the business (the domain experts).

Once we know the domain model what do we do with it? In DDD we implement it directly in code. This is possible because DDD defines patterns to build our domain model which can be implemented in code too. The model can then be used by higher-level controllers to execute use cases.

The last concept is: Speak a ubiquitous language within a bounded context. The same language should be used through conversations, the domain model and in code. The ubiquitous language allows us to communicate effectively and prevents misunderstandings. The strategic pattern “Bounded context” aims to divide software along the domain boundaries. Ubiquitous language is always valid within a given context.

The Patterns

Basic DDD patterns can be divided into two kinds of patterns: tactical and strategic. Tactical patterns are used while modeling the domain and in code. Strategic patterns are more high level and are used to structure the software on an architectural level. We will go into the details of each pattern through the series. Therefore I list them only very briefly here.

Tactical Patterns (or building blocks in original DDD terms):

  • Entity – Similar to objects in classic object-oriented design but with a focus on identity over time.
  • Value Object – Immutable entity identified by its attributes.
  • Factory – Super pattern for some of the GoF creational patterns.
  • Service – Stateless object which encapsulates domain logic that cannot reasonably put on an entity or value object.
  • Aggregate – Encapsulates multiple entities and value objects.
  • Repository – Library for obtaining access to aggregates.
  • Module – Structure objects on a higher level to reduce cognitive overload.

Strategic patterns and concepts:

  • Bounded context – Define boundaries around domain areas and reflect them in software.
  • Context Map – Model of the different bounded contexts of the system.
  • Model Integrity Patterns – Ways to model the connections between multiple bounded contexts.
  • Core Domain – Find the part of your model where the most business value lies and distill it into the highest priority context.

Supple Design

Supple design is the concept of designing the software in a way that feels natural when developing and maintaining it. The following patterns give some advice on how to achieve this property of software.

  • Intention-revealing interfaces – Give the elements of software meaningful names, use the ubiquitous language
  • Side-effect-free functions – Prefer functions that return results instead of manipulating some state
  • Assertions – State post-conditions of operations and invariants of classes explicitly
  • Conceptual Contours – Decompose elements of software into cohesive units
  • Standalone Classes – Minimize dependencies to reduce the mental load
  • Closure of operations – Where possible operations should return the same type as their argument(s)
  • Declarative design – If possible use a declarative design/program style

Don’t worry if these very short descriptions leave some question marks in your head. These are concepts that cannot simply be explained in one or two sentences. I will try to explain them in the further posts of these series. Meanwhile, if you are curious, see this article for a bit more information.

Distillation of the Core

Distillation of the core domain enables us to focus on the most valuable part of our domain model. Evans touches multiple patterns or strategies of how to approach the distillation.

  • Generic Subdomains – Extract subdomains that are not the main reason you build the system
  • Domain Vision Statement – High-level vision of the system that helps to define the core domain
  • Highlighted Core – Define which parts of model belong to the core but without extracting it (yet)
  • Cohesive Mechanisms – Identify parts of the model that form a general know mechanisms
  • Segregated Core – Remove supporting functionality from core objects
  • Abstract Core – Aim for abstract core concepts that specialized subdomains can use

Large-Scale Structure

Large-scale structure concepts organize the system on a component or layer level. It guides developers on where to find functionality and where to place a new one.

The large-scale structure is not the same as classic architecture. It is driven by the domain and should, therefore, be based on domain concepts rather than technical concerns.

  • Evolving order – Let the large-scale structure evolve over time
  • System metaphor – Look for an overarching metaphor of the system and make it explicit
  • Responsibility Layers – Organize the domain model across multiple layers
  • Knowledge level – Allow configuration of core operations from a knowledge level
  • Pluggable component framework – Abstract core with a plugin infrastructure

Wrap up / Final Thoughts

It seems that DDD consists of many concepts and patterns. However, don’t be scared, many of the overlap and together form a domain-centric way of thinking about software design.

When we take a look at our profession as a whole, DDD is concerned only with a small part of our responsibilities. Recently I read a blog post by Bob Martin where he reviews the XP process. He writes that metaphor in XP became DDD. The metaphor is only one of twelve practices in XP.

[Eva04] Eric Evans: Domain-Driven Design – Tackling Complexity in the Heart of Software (homepage)

[Sch17] M. Schimak: Domain-Driven Design? Na klar, das „blaue Buch“! – Mit „DDD“ (Domain-Driven- Design) zur gemeinsamen Sprache für Business und IT (http://www.sigs.de/public/os/2017/03/Schimak_OS_03_17_hdtz.pdf)