DDD: guidance on updating multiple properties of entities
Asked Answered
P

2

14

So, i decided to learn DDD as it seems to solve some architectural problems i have been facing. While there are lots of videos and sample blogs, i have not encountered one that guides me to solve the following scenario:

Suppose i have the entity

public class EventOrganizer : IEntity
{
    public Guid Id { get; }

    public string Name { get; }

    public PhoneNumber PrimaryPhone { get; }

    public PhoneNumber AlternatePhone { get; private set; }

    public Email Email { get; private set; }

    public EventOrganizer(string name, PhoneNumber primaryPhoneNr)
    {
        #region validations

        if (primaryPhoneNr == null) throw new ArgumentNullException(nameof(primaryPhoneNr));

        //validates minimum length, nullity and special characters
        Validator.AsPersonName(name);

        #endregion

        Id = new Guid();
        Name = name;
        PrimaryPhone = primaryPhoneNr;
    }
}    

My problem is: suppose this will be converted and fed to a MVC view and the user wants to update the AlternatePhone, the Email and a lot of other properties that make sense to exist within this entity for the given bounded context (not shown for brevity)

I understand that the correct guidance is to have a method for each operation, but (AND I KNOW ITS KINDA OF ANTI-PATTERN) i cant help but wonder if this wont end up triggering multiple update calls on the database.

How is this handled ? somewhere down the line, will there be something that maps my EventOrganizer to something - say DbEventOrganizer and gathers all changes made to the domain entity and apply those in a single go?

Purism answered 13/11, 2015 at 17:11 Comment(0)
R
23

DDD is better suited for task-based UIs. What you describe is very CRUD-oriented. In your case, individual properties are treated as independent data fields where one or many of these can be updated by a single generic business operation (update).

You will have to perform a deeper analysis of your domain than this if you want to be successfull with DDD.

Why would someone update all those fields together? What implicit business operation is the user trying to achieve by doing that? Is there a more concrete business process that is expressed by changing PrimaryPhone, AlternatePhone and Email together?

Perhaps that is changing the ContactInformation of an EventOrganizer? If that's the case then you could model a single ChangeContactInformation operation on EventOrganizer. Your UI would then send a ChangeContactInformation command rather than an update command.

As for the persistence of your aggregate roots (AR), this is usually handled by an ORM like NHibernate if you are using a RDBMS. However, there are other ways to persist your ARs like Event Sourcing, NoSQL DBs and even storing JSON or any other data inter-change formats in a RDBMS.

Rally answered 15/11, 2015 at 22:36 Comment(3)
Thanks. while i deffo need a deeper analysis on my domain, this is what i needed; i really need a ChangeContactinformation operation, its just that this being my first DDD project i was hung up on my CRUD oriented mind. Thanks a bunch !Purism
@Sergio I'm glad I could help! Just to be clear, the ContactInformation should be a value object. Do not pass individual VOs like PrimaryPhone, Email, etc as separate arguments to the ChangeContactInformation method.Rally
If I need a business/behavior that updates almost all fields of the User domain model, such as updating user information (firstName, nickname, avatar, age, address, country/region, what's up, etc...) on the Profile page, how should I add this method to the User domain model? Should the method receive many primitive/value-object type parameters or a DTO object?Plutus
Q
2

You question is quite broad!

EventOrganizer itself should not be updating anything. You should keep your update code quite separate from the entity. A different class would take an EventOrganizer object and update the DB. This is called 'persistence ignorance' and makes the code a lot more modular and cohesive.

It would be common to create a View Model - a class whose purpose is to provide the View with the exact data it needs in the exact form it needs. You would need to create the View Model from your EventOrganizer, after which the View can update it - programmatically or with binding. When you're ready to save the changes, you'll need to update your EventOrganizer from the View Model and pass it onto the updater. This seems like a layer you don't need when the project is small and simple, but it is becomes invaluable as the complexity builds.

Quasijudicial answered 13/11, 2015 at 17:42 Comment(5)
my point is, since im updating a property at a time with a single method, ina scenatio where someone updates say 10 properties how would these 10 separate updates relate to my to separate methods on EventOrganizer and then to just one sql update instruction?Purism
Setting the property on an entity doesn't need to be wrapped in a method unless the entity needs to know of the property change. An entity like EventOrganizer doesn't have a lot of internal logic, so setting its properties directly is fine. Unless you're implementing some sort of auditing, you don't need to know which properties have changed - tracking at that level is not necessary. Instead, you'd write the whole entity back into the database in one hit - including properties that haven't changed. Or write your SQL to check the new values against the old and only write what has changed.Quasijudicial
I'd recommend looking at an ORM framework like Entity Framework or nHibernate. You don't need to write the SQL statements, you just to update the objects and tell the ORM to update the database.Quasijudicial
They way you explain binding a ViewModel to a domain object is CRUDish. That's not how it works in practice. Your ViewModel is useful to capture information about a specific command and validate the command on the UI. However, once the controller receives the VM it should decompose it into a command an ApplicationService can understand. The ApplicationService will then be responsible to invoke the command on the proper aggregate root. There's no property-to-property mapping between the VM and the aggregate roots.Rally
Fair comment - I was over-simplifying.Quasijudicial

© 2022 - 2024 — McMap. All rights reserved.