I was reading a similar question on SO: How update an entity inside Aggregate, but I'm still not sure how a user interface should interact with entities inside an aggregate.
Let's say I have a User
, with a bunch of Address
es. User is the aggregate root, while Address only exists within the aggregate.
On a web inteface, a user can edit his addresses. Basically, what happens is:
- The user sees a list of addresses on its web interface
- He clicks on an address, and gets redirected to this page:
edit-address?user=1&address=2
- On this page, he gets a form where he can modify this address.
I we decided to bypass the aggregate root, this would be straightforward:
- We would directly load the
Address
with itsId
- We would update it, then save it
Because we want to do it the DDD way, we have different solutions:
Either we ask the User to get this Address by Id:
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 doesn't have much more control over what's done with the address. It just returns a reference to it, so that's not much different from bypassing the aggregate.
Or we tell the aggregate to update an existing address:
user.updateAddress(id, "12345", "New York");
em.persist(user);
Now the aggregate has control over what's done with this address, and can take any necessary action that goes with updating an address.
Or we treat the Address as a value object, and we don't update our
Address
, but rather delete it and recreate it: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 that an Address cannot be an Entity. Then, what if it needs to be treated as an entity, for example because another business object within the aggregate has a reference to it?
I'm pretty sure I'm missing something here to correctly understand the aggregate concept and how it's used in real life examples, so please don't hesitate to give your comments!
changeAddress()
method. The example above is an oversimplification, and an address might be composed of a dozen fields, including street name, building number,LatLng
point for the exact location on the map, etc. What do you suggest then, put all these parameters in the method arguments, or create some kind of transient object from the form (would it be anAddress
object as well?), and pass it as an argument to this method? – Judejudea