简体   繁体   中英

Which class should be responsible for creating ID for entity?

I'm struggling a little bit with following problem. Let's say I want to manage dependencies in my project, so my domain won't depend on any external stuff - in this problem on repository. In this example let's say my domain is in project.Domain .

To do so I declared interface for my repository in project.Domain , which I implement in project.Infrastructure . Reading DDD Red Book by Vernon I noticed, that he suggests that method for creating new ID for aggregate should be placed in repository like:

public class EntityRepository
{
    public EntityId NextIdentity()
    {
        // create new instance of EntityId
    }
 }

Inside this EntityId object would be GUID but I want to explicitly model my ID, so that's why I'm not using plain GUIDs. I also know I could skip this problem completely and generate GUID on the database side, but for sake of this argument let's assume that I really want to generate it inside my application.

Right now I'm just thinking - are there any specific reasons for this method to be placed inside repository like Vernon suggests or I could implement identity creation for example inside entity itself like

public class Entity
{
    public static EntityId NextIdentity()
    {
        // create new instance of EntityId
    }
 }

You could place it in the repository as Vernon says, but another idea would be to place a factory inside the constructor of your base entity that creates the identifier. In this way you have identifiers before you even interact with repositories and you could define implementation per your ID generation strategy. Repository could include a connection to something, like a web service or a database which can be costly and unavailable.

There are good strategies ( especially with GUID ) that allow good handling of identifiers. This also makes your application fully independent of the outside world.

This also enables you to have different identifier types throughout your application if the need arises.

For eg.

public abstract class Entity<TKey>
{
    public TKey Id { get; }

    protected Entity() { }

    protected Entity(IIdentityFactory<TKey> identityFactory)
    {
        if (identityFactory == null)
            throw new ArgumentNullException(nameof(identityFactory));

        Id = identityFactory.CreateIdentity();
    }
}

Yes, you could bypass the call to the repository and just generate the identity on the Entity. The problem, however, is that you've broken the core idea behind the repository: keeping everything related to entity storage isolated from the entity itself.

I would say keep the NextIdentity method in the respository, and still use it, even if you are only generating the GUID's client-side. The benefit is that in some future where you want to change how the identity's are being seeded, you can support that through the repository. Whereas, if you go with the approach directly on the Entity, then you would have to refactor later to support such a change.

Also, consider scenarios where you would use different repositories in such cases like testing. ie. you might want to generate two identities with the same ID and perform clash testing or "does this fail properly". Having a repository handle the generation gives you opportunity to get creative in such ways, without making completely unique test cases that don't mimic what actual production calls would occur.

TLDR; Keep it in the repository, even if your identifier can be client-side generated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM