Skip to content

Entities

In Domain-Driven Design (DDD), an Entity is an object that is not primarily defined by its attributes, but rather by a thread of continuity and its identity. This means that even if some or all the attributes (also known as the state) of an Entity change, it’s still the same Entity.

Here are a few characteristics of Entities:

  1. Identity: Each instance of an Entity has a unique identity. This identity doesn’t change even when any or all of the attributes of the Entity change.

  2. Mutability: Unlike Value Objects, Entities are mutable. This means that the state of an Entity can change, but it’s still the same Entity.

  3. Encapsulation: Entities encapsulate both state and behavior that depends on that state.

In practice, you would likely add more complex behavior to the User class, and you would want to ensure that instances are retrieved and saved from a database or other persistence mechanism, typically through a Repository. It’s also common to use a factory to ensure that Entities are created in a valid state and to abstract away any complexity in their creation.

Entities are the backbone of your domain model, and encapsulate the key business rules and behaviors of your system. They’re typically where most of the interesting work in your domain happens. Entities will often reference other Entities and Value Objects, and will be referenced by Aggregate Roots, which control the lifecycle of Entities.

Managing identity

The identity of an entity is typically managed via a unique identifier. This could be a natural identifier that’s derived from the entity’s attributes, or a synthetic (or surrogate) identifier that’s generated by the system and has no inherent meaning.

In most cases, particularly for complex or long-lived entities, a synthetic identifier is preferred. This ensures that the entity’s identity is stable and doesn’t depend on any of its mutable attributes.

There are several common ways to generate synthetic identifiers:

  1. Sequences: Many databases support sequences, which generate a unique number each time they’re called. This can be used as the entity’s identifier.

  2. UUIDs: A Universally Unique Identifier (UUID) is a 128-bit number that’s generated in such a way as to be globally unique. UUIDs are a good choice if you need to generate identifiers in a distributed system or if you want to generate identifiers in the application layer rather than in the database.

  3. Database-generated identifiers: Many databases can automatically generate a unique identifier for each row in a table. This is often done with an auto-incrementing integer column.

  4. Combination of attributes: In some cases, a unique identifier can be generated from a combination of different attributes of an entity. For example, in a system without synthetic identifiers, a User entity might use a combination of first name, last name, and date of birth as a unique identifier.

Once an identifier is assigned to an entity, it should never be changed. The identifier ensures that we can track the entity as a continuous thread throughout the system, even if all of its other attributes change.

In Python, for example, an entity’s identifier might be assigned when it’s created and then stored in a read-only property:

class User:
    def __init__(self, id, name):
        self._id = id
        self.name = name

    @property
    def id(self):
        return self._id

In this example, the User entity’s id is set when it’s created and cannot be changed afterwards. It’s exposed through a read-only property, ensuring that it remains stable and unchangeable.

Page last modified: 2024-02-13 10:02:46