Entity is for Identity

Continuing on our Domain Driven Design thread, we will talk about domain specific objects in the next few posts.

We start with the Entity. Entity is one of the three main base objects in our domain core. It is not to be confused with an entity in EntityFramework!

In most applications there will be some kind of persistence meaning there will be objects that outlive the lifetime of a usage session. We need to keep track of these objects between sessions and we need to be able to easily identify them.

What is identity?

  • Identity is a property that is unique across all instances of an object
    • Two objects with the same attributes (i.e. they look the same), but with different identity, are not the same object
  • Identity is not determined by object attributes
    • Two objects with different attributes but the same identity, is the same object, although the state of the objects are different

Those familiar with SQL will recognize that we usually have a primary key column, and that this is usually an integer generated by the database. As this is a perfect example of identity, it is not the only valid case.

  • As stated Integers (or an equivalent number type) are used.
  • Strings can also be used. A person's name is generally not a good identity as names are not unique. Types in a type table are usually unique and might be a use case. (I need to explore this more)
  • In some cases an application has to rely on itself to generate an identity and a Guid works great for this purpose.
  • Value objects. This can be an object that can be uniquely identified by its attributes. We will discuss value objects in a later post.

What is Entity?

  • An Entity has Identity as stated above
  • An Entity is responsible for tracking it's state and the rules regulating it's lifecycle (from DDD Reference )

An entity is the abstraction we use to model objects with identity.

How would this look? examples in c#

First of all, we will label all our objects with identity as an entity using an interface.

public interface IEntity  
{
    int Id { get; }
}

Using it like this means that we will always use integers as identity and that we will compare entities using the Id property.

We can improve our entity by allowing different types as identity.

public interface IEntity<out TKey>  
{
    TKey Id { get; }
}

When comparing an identity that is complex, using id == id might not be enough. In these cases we will add a IsSameAs method to our interface. Using this method we can explicitly state how we want to compare identity.

public interface IComplexEntity<out TKey, in TEntity>  
{
    TKey Id { get; }
    bool IsSameAs(TEntity entity);
}
//Object Definition
public class User : IComplexEntity<int, User>  

We can even reuse IEntity<TKey> and only apply IsSameAs where needed.

public interface IComparableEntity<out TKey, in TEntity> : IEntity<TKey>

//We can even use System.IComparable<>
public interface IEntityInheritingIComparable<out TKey, in TEntity> : IComparable<TEntity>  

The method you choose will highly depend on the problem you need to solve. The right way is the way that best fits your model and is agreed upon by your team.

Where does entity live?

Entity lives at the center of your domain layer. I like to place it in a folder called abstractions together with my other high level DDD concepts. I have also seen this namespace called 'shared' or 'core'. For those who really like separation you can move all your abstractions into its own project.

I have updated the SimpleDDD project to contain entities.