Entities
Entities
Every aggregate root is also an entity. So, these rules are valid for aggregate roots too unless aggregate root rules override them.
Do define entities in the domain layer.
Primary Constructor
Do define a primary constructor that ensures the validity of the entity on creation. Primary constructors are used to create a new instance of the entity by the application code.
Do define primary constructor as
public
,internal
orprotected internal
based on the requirements. If it's not public, the entity is expected to be created by a domain service.Do always initialize sub collections in the primary constructor.
Do not generate
Guid
keys inside the constructor. Get it as a parameter, so the calling code will useIGuidGenerator
to generate a newGuid
value.
Parameterless Constructor
Do always define a
protected
parameterless constructor to be compatible with ORMs.
References
Do always reference to other aggregate roots by Id. Never add navigation properties to other aggregate roots.
Other Class Members
Do always define properties and methods as
virtual
(exceptprivate
methods, obviously). Because some ORMs and dynamic proxy tools require it.Do keep the entity as always valid and consistent within its own boundary.
Do define properties with
private
,protected
,internal
orprotected internal
setter where it is needed to protect the entity consistency and validity.Do define
public
,internal
orprotected internal
(virtual) methods to change the properties (with non-public setters) if necessary.Do return the entity object (
this
) from the setter methods.
Aggregate Roots
Primary Keys
Do always use a Id property for the aggregate root key.
Do not use composite keys for aggregate roots.
Do use Guid as the primary key of all aggregate roots.
Base Class
Do inherit from the
AggregateRoot<TKey>
or one of the audited classes (CreationAuditedAggregateRoot<TKey>
,AuditedAggregateRoot<TKey>
orFullAuditedAggregateRoot<TKey>
) based on requirements.
Aggregate Boundary
Do keep aggregates as small as possible. Most of the aggregates will only have primitive properties and will not have sub collections. Consider these as design decisions:
Performance & memory cost of loading & saving aggregates (keep in mind that an aggregate is normally loaded & saved as a single unit). Larger aggregates will consume more CPU & memory.
Consistency & validity boundary.
Example
Aggregate Root
The Entity
Last updated