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) {
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.
kstaruch
source share