Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persistance ID's and Domain Model Entities

I was curious on what peoples thoughts are on keeping the Id of a DAL entity as a property of the Domain Entity, at the absolute most a read-only property.

My first thoughts was that this is ok to do but the more I think about it the more I dislike the idea. After all the domain model is supposed to be completely unaware of the how data is persisted, and keeping and Id property on each domain model is a less-than-subtle indication. The persistence layer may be something that doesn't require primary keys, or another property exposed in the domain model may be a suitable candidate for identification, a model no. perhaps.

But then that got me thinking, for domain models that do not have a reliable means of uniquely identifying an entry in a database persistence layer, how are they to identify entries when it comes to updating or deleting?

A dictionary based on weak reference keys could do the trick; WeakDictionary<DomainEntity, PrimaryKeyType>. This dictionary would be a part of the repository implementation, whenever the client of the repository Fetch's a collection of DomainEntity a weak reference to the entity and its persistence layer Id is stored in this internal dictionary such then when comes time to return the modified entity to the repository for updating the persistence layer, the following could be done to get back the Id

PrimaryKeyType id = default(PrimaryKeyType);
if (!weakDictionary.TryGetValue(someDomainEntity, out id))
     // id not found, throw exception? custom or otherwise..

// id found, continue happily mapping domain model back to data model.

The benefits of this approach as I see it, is the domain entity need not maintain its persistence layer specific id and the repository forces you to have a legitimate Domain Entity obtained either by some call to a Fetch... method or the Add/CreateNew method, else should you try to update/delete the entity it will throw an exception.

I'm aware that this probably over-engineering and I should just buckle down and get pragmatic, I was just curious on what other people thought about this.


I don't want to start another thread just for this minor question as it is somewhat related. But since it is relatively recently I have started looking into DDD (though in this case my database came first) I wondered if I could confirm that I have the right mindset for Domain Entities, here is a cut down example of my Employee domain entity.

public class Employee : DomainEntity
{
    public string FirstName { get; }
    public string LastName { get; }
    public UserGroup Group { get; }
    // etc..


    // only construct valid employees
    public Employee(string firstName, string lastName, SecureString password, UserGroup group);

    // validate, update. (not sure about this one.. pulled it 
    // from an open source project, I think that names should be able to be set individually).
    AssignName(string firstName, string lastName);

    // validate, update.
    ResetPassword(SecureString oldPassword, SecureString newPassword);

    // etc..
}

Thank you!

like image 411
rtlayzell Avatar asked May 02 '14 01:05

rtlayzell


1 Answers

Your proposal of using weak references has one major flaw.

As you might know, domain entities have the important characteristic in that they must have identity. This is important for comparison reasons. If two entities have the same identity, regardless of the values of their properties, then they are considered equal:

Entity1 == Entity2 ⇔ Entity1.Identity == Entity2.Identity

A typical "design pattern" would be to inherit all entities from a DomainEntity<T> abstract class, which overrides the comparison of these objects and compares by identity.

Now, consider your approach of using a weak reference look up. Let's take an example:

You fetch an Entity1, say the "Reegan Layzell" user, from a repository. Then you fetch the exact same "Reegan Layzell" entity from the repository again as Entity2. You now have the same entity in your domain in two objects. But they have difference references (of course).

When comparing, these entities will not be considered equal in your domain.

I admire your fear of introducing database concerns into your domain model, but propagating the database ID into your entities is hardly going to affect the quality of your models and it will save you a lot of trouble. Like you said, we need to be pragmatic.

With regards to your Employee example: Does AssignName really make sense? In reality, can an employee's name really change after creation? Other than that, it looks like you have the right idea. I highly recommend you watch this: Crafting Wicked Domain Models by Jimmy Bogard.

like image 142
Dave New Avatar answered Sep 29 '22 22:09

Dave New