0

How should looks update method signature in aggregate root? For example I need to update user address. I have multiple ways to do this, and don't know which is better ("domain driven design way"). First way is to create method in User which get UserAddress as argument:

public void updateAddress(UserAddress address) {
    // update logic
}

But in this case external components that use User.updateAddress(UserAddress address), know inner representation of user address.

Other way is to create metods with many arguments:

public void updateAddress(String city, String street, String country) {
     //update logic    
} 

Or I can create some value object:

public void updateAddress(AddressDTO addressDto) {
    // update logic
}

Which way is better?

public class User {
    private Long id;
    private List<UserAddress> addresses;
    // other fields and methods
}

public class UserAddress {
    private Long id;
    private String type;
    private Boolean isMain;
    private Address address;

    public void update(Address address, Boolean isMain) {}
}

public class Address {
    // fields like city, street etc
}
0

Which way is better?

As far as I know, there's no single simple answer to this.

Within the domain model; it is a good idea to express your data as Value Objects rather than simply exposing the primitive types used to represent them. That means that the signature of entities should normally be expressed in terms of values, not primitive types.

Aggregate roots are typically just entities that happen to sit in the root position of their aggregate. So you would normally just lift the same API.

However, there is a real question of passing data across the boundary to the model, and whether or not you should treat the aggregate root as living at the boundary, or inside of it.

The usual choice is that the root lives within the boundary -- that the application is responsible for arranging the data into the correct shape before passing it to the model.

This is often convenient for input validation; if the application is responsible for shaping the data, then it is in the best position to decide how to handle invalid inputs.

That suggests

public void updateAddress(City city, Street street, Country country) {
    //update logic    
} 

or

public void updateAddress(CityName city, StreetName street, CountryName country) {
    //update logic    
} 

rather than

public void updateAddress(String city, String street, String country) {
     //update logic    
} 

For instance, if you examine the Cargo entity from the DDDSample, you'll notice that all of the methods are expressed in other model types. Primitive data types are typically restricted to values like UnLocode.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.