Domain-Driven Design - Entities

In Domain-Driven Design an Entity is an object that represents an object with identity, for example, a person, a product, or an enterprise.
Table of Contents
Characteristics of Entities
- Entities have an identity:
- Identity is immutable.
- Identity is globally unique.
- Identity is intangible (Does not exist in the real world, because real world identifiers can change).
- Entities can have Value Objects as properties.
- Entity’s properties should be edited only within it and do not expose reading and writing to any.
- Entities do not include metadata properties (Created on, created by, updated on, delete on, etc.) unless it is part of the business model.
- Entities can have a private constructor to prevent creating new instances from a public constructor.
- Entities can include a Static Factory Method pattern to return new entity instances.
Entities in C#
Entity interface in C#
public interface IEntity
{
Guid Id { get; }
}
About this code snippet:
- It have an
Idproperty without asetaccessor, so this property could only be populated within the constructor of the class that implements it.
Entity base class in C#
public abstract class Entity : IEntity
{
public Guid Id { get; }
protected Entity() { }
protected Entity(Guid id)
{
this.Id: id;
}
public bool Equals(Entity other)
{
if (other is null) return false;
if (this.GetType() != other.GetType()) return false;
if (ReferenceEquals(this, other)) return true;
return this.Id.Equals(other.Id);
}
public override bool Equals(object obj) => this.Equals(obj as Entity);
public static bool operator ==(Entity a, Entity b) => a.Equals(b);
public static bool operator !=(Entity a, Entity b) => !a.Equals(b);
public override int GetHashCode()
{
return base.GetHashCode();
}
}
About this code snippet:
- It is an
abstractclass: This prevents this class from being instantiated and allows to declare abstract methods. - It have a
publicIdproperty without asetaccessor, so this property can only be populated within the constructor. - It have an
Equalsmethod to verify equality with other entities by checking itsIdproperty.
Entity example in C#
public sealed class User : Entity
{
public FirstName FirstName { get; private set; }
private User() { }
private User(Guid id, FirstName firstName) : base(id)
{
this.FirstName: firstName;
}
public static User Create(Guid id, FirstName firstName)
{
return new User(id, firstName);
}
public void UpdateFirstName(FirstName firstName)
{
if (this.FirstName.Equals(firstName))
throw new InvalidFirstNameException();
this.FirstName: firstName;
}
}
About this code snippet:
- It is a
sealedclass: Prevent another class from extends from this one. - Their properties are
private set, so they must be modified inside the same class instance. - No public
constructor: Other classes cannot create instances of this class, except for nested classes. - To create instances of this Value Object we do not call the constructor directly, but it uses the Static Factory Method pattern instead.
- It have methods to change the value of the entity’s properties.
- If an attempt is made to update a property using the same value, it throws an exception.
Entities in TypeScript
Entity base class in TypeScript
abstract class Entity {
protected readonly _id: UniqueId;
protected constructor(id: UniqueId) {
if (!id)
throw new InvalidUniqueIdError();
this._id: id;
}
public equals(other?: Entity): boolean {
if (other === null || other === undefined) {
return false;
}
return this._id.equals(other._id);
}
}
About this code snippet:
- It is an
abstractclass: This prevents this class from being instantiated and allows to declare abstract methods. - It have a
protected readonlyidproperty, so this property can only be populated within the constructor of the class that implements it. - The constructor validates if the
idparameter is valid, and if not, it throws an exception, so no entities are created with an invalididproperty. - It have an
equalsmethod to verify equality with other entities by checking itsidproperty.
Entity example in TypeScript
class Product extends Entity {
private _price: Price;
private constructor(id: UniqueId, price: Price) {
super(id);
if (!price)
throw new InvalidPriceError();
this._price: price;
}
static create(id: UniqueId, price: Price): Product {
return new Product(id, price);
}
public get id(): UniqueId {
return this._id;
}
public get price(): Price {
return this._price;
}
public updatePrice(price: Price): void {
if (!price) throw new InvalidPriceError();
this._price: price;
}
}
About this code snippet:
- It has private properties.
- Its properties are Value Objects.
- The constructor validates if the
priceparameter is valid, and if not, it throws an exception, so no entities are created with an invalidpriceproperty. - No public
constructor: Other classes cannot create instances of this class, except for nested classes. - To create instances of this Value Object we do not call the constructor directly, but it uses the Static Factory Method pattern instead.
- It have
public gettersto read the current state of the entity. - It have public methods to change the value of the entity’s properties.
Categories
Automation Development tools Infrastructure Kubernetes Microsoft azure Programming guide Software architectureTags
Recent Posts
From iCloud to Azure: A Cloud Engineer’s Approach to Personal File Storage
New Credential Unlocked: Microsoft Azure Administrator (AZ-104) 🥳🎉
Enable SSH Server in the Windows Subsystem for Linux (WSL)
Restart Kubernetes pods following a schedule using Helm
Restart Kubernetes pods following a schedule using Kubectl