Updating an object inside an aggregate

I read a similar question about SO: How to update an entity inside Aggregate , but I'm still not sure how the user interface should interact with objects inside the aggregate.

Say I have a User , with a bunch of Address es. The user is an aggregated root, and the address exists only in aggregate.

In the web interface, the user can edit their addresses. Basically, the following happens:

  • The user sees a list of addresses on his web interface
  • He clicks on the address and redirects to this page: edit-address?user=1&address=2
  • On this page, he receives a form in which he can change this address.

We decided to bypass the cumulative root, it would be simple:

  • We directly downloaded Address using Id
  • We will update it and then save it.

Since we want to do this using the DDD method, we have different solutions:

  • Or we will ask the user to get this address by identifier :

    address = user.getAddress(id);
    address.setPostCode("12345");
    address.setCity("New York");
    em.persist(user);

    The problem with this approach is IMO, that the aggregate root still does not have much more control over what is done with the address. It just returns a link to it, so it is not much different from an aggregate bypass.

  • Or we will inform the aggregate about updating the existing address :

    user.updateAddress(id, "12345", "New York");
    em.persist(user);

    Now it aggregates control over what has been done with this address, and can take any necessary actions related to updating the address.

  • Or we consider the address as an object of value, and we do not update our Address , but rather delete it and recreate :

    user.removeAddress(id);
    address = new Address();
    address.setPostCode("12345");
    address.setCity("New York");
    user.addAddress(address);
    em.persist(user);

    This last solution looks elegant, but means the address cannot be an entity. Then, what if it needs to be considered as an entity, for example, because another business object inside the aggregate has a link to it?

I am sure that something is missing for me to correctly understand the general concept and how it is used in real life examples, so please feel free to give your comments!

+6
orm aggregate domain-driven-design aggregateroot
source share
1 answer

No, you haven’t lost anything - in most cases the best option would be number 2 (although I would call this method changeAddress and then updateAdress - the update seems so non-DDD) and regardless of whether the address is an Entity or Value object. With Ubiquitous Language, you would rather say that the User has changed his address, so exactly how you should model it is the changeAddress method, which allows you to decide whether there will be update properties (if Address is Entity) or to assign a completely new object (when it is VO )

The following code example assumes the most common scenario - Address as VO:

  public void ChangeAddress(AddressParams addressParams) { // here we might include some validation address = new Address(addressParams); // here we might include additional actions related with changing address // for example marking user as required to confirm address before // next billing } 

What is important in this example is that after the address is created, it is considered valid - there cannot be an invalid address object in your aggregate. However, it does not matter whether you should follow this pattern or not, it depends on your actual domain - there is no way to follow. This is one of the most common though.

And yes, you should always perform operations on your entities, going through the cumulative root - the reason for this was given in many answers to SO (for example, in this Basic general question ).

Whether something is an entity or VO depends on the requirements and your domain. The primary time address is only a Value object, because there is no difference between two addresses with the same values ​​and addresses that do not change during their lifetime. But then again, this in most cases depends on which one you model.

Another example - for most domains a Money will be an Object of value - $ 10 - $ 10, it does not have an identifier, except for the amount. However, if you model a domain that deals with money at the account level, each account will have its own identification (expressed with a unique number of some kind), so this will be Entity.

+4
source share

All Articles