4
votes

I’m struggling designing this system where an address is the most central piece of information. Now in this case, an address is not just a few lines of strings. We’re storing municipalities (code, name), district (post code, name), streets (code, name), house number on a street in a specific district belonging to a municipal. It's a very normalized scheme.

So we have the entities Municipal, District, Street and HouseNumber each with relations to each other, defining a complete address for a person (or something else).

Now I have been trying to figure out if it would make any sense having an aggregate root named Address? An Address entity (aggregate root) would then have references to HouseNumber, Street, District and Municipal. Then a person would be associated to an Address.

Strictly speaking this aggregate root is not necessary, but if I don’t have it, I would have to traverse many objects to obtain the full address. Does it make any sense to create an aggregate root based on that argument?

A person will never reference anything but the aggregate root in this case, however the UI might display only Municipalities (when browsing addresses, etc.). Is this a violation of the aggregate root idea?

I would really like your advice and take on this problem. Any help will be much appreciated!


A little update from another discussion about my problem:

There is some invariants needed to be managed in the aggregate. For example; I can't have a house number on a street thats in one district/municipality, where the postal box is in another different district/municipality. So when assigning a post box to an address/person, I need to make sure that they are in the same district.

Also there are some consistency boundaries (if I understood this concept the right way). If I have an address, this must have a house number in a district on a street (in that district). A street can span multiple districts so it's important to ensure that the house number on that street is in the correct district.


Update about designing the aggregate:

A house number is actually the entry point for an address. A house number is associated with a street and a district. So a person is associated to a house number. What I also want to define is if a person has "postal responsibility" for that house number. Introducing the aggregate root Address, makes the person associate with that instead of the house number. In the database, the aggregate Address will contain a 1-1 association to a house number, and the Address has a 1-* to a Person. Where should I store the value indicating that the person has postal responsibility or not? Should I do this in the Address aggregate? Or where would you put it? And the same goes for my entities - where should I indicate if the person has a postal responsibility?

3
All of this screams for some code. Can't hold all that info in memory. Will return to Your question after work. :) - Arnis Lapsa
After all - you modeled it as You wanted to? Maybe it would be nice to include UML or smthg in Your question. I think this question+answers got quite valuable info. - Arnis Lapsa
We ended up with a design that we think is good, but haven't fully decided on what to be an aggregate root yet. However I got a good picture of why and why not to make Address as an aggregate. I will post my solution one of the coming days. - Tommy Jakobsen

3 Answers

8
votes

To distinguish if address is value object or entity, ask Yourself a question - if person address changes and 2nd person had same address - will both change? If they both changes - address gets promoted to entity (cause address identity is important and not value).

To distinguish if address is entity or an aggregate root, ask Yourself a question - does address make any sense on it's own or it's always tied to person, is modified through it, deleted together with it? If it's not tied with person but exists on it's own (in model You are modeling and not reality), then address is an aggregate root.


Strictly speaking this aggregate root is not necessary, but if I don’t have it, I would have to traverse many objects to obtain the full address. Does it make any sense to create an aggregate root based on that argument?

No it does not. Technical issues shouldn't mess with Your domain. Entity can work as a 'sub-aggregate', address can hold together municipality, city, etc. and still be just an entity (cause it makes no sense w/o person).

A person will never reference anything but the aggregate root in this case, however the UI might display only Municipalities (when browsing addresses, etc.). Is this a violation of the aggregate root idea?

Presentation shouldn't mess with Your domain too. As far as i see - it's perfectly fine if You are showing only list of entities and hiding aggregates they belong to.


Two persons can be associated to the same address, and if one of them move the other doesn't move automatically.

Question is - how You want to model that moving process?

I see 2 ways:

  1. When person #1 moves, address is modified but address of person #2 is not the same address and hence - is not affected. In this case - address is just an entity.
  2. When person #1 moves, moving process switches address to another one. In this case - address is an aggregate root.

Addresses exists on their own and if a person move to an address, he gets associated with it.

This one means that You want to stick with 2nd way (when address is an aggregate root). It's fine and there is nothing wrong, but You should re-check if address can be demoted to entity cause that would make Your domain model less complex.


And keep in mind - there isn't "The model", there are only "A model"s. You can't model reality to mimic it perfectly, You can only model some part of it to solve specific problems.

This is why it's so hard to answer ddd related questions.
No one knows Your problems You are trying to solve.


If I understand it correctly (http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - the part about aggregates), then whether an address can exist without a person (or other addressee) is irrelevant; the question is whether the address-constituents can exist or be accessed without the address. If they can, Address shouldn't be an aggregate root.

It is relevant. If address can't exist without a person (which is not a case here) - it's inevitably demoted as an entity (cause it makes no sense without person) or value object (if address itself has no identity). Otherwise - You are just introducing unnecessary aggregate root.

It's fine if aggregate root contains references to other aggregate roots (but not entities of other aggregate roots). Therefore - address constituents can be aggregate roots too (Municipality that is referenced in PostOffice) and that wouldn't change if address itself is entity or an aggregate root.

1
votes

Aggregate, in my opinion, should be created if

  1. there is a containment relationship with its associated objects
  2. the objects of an Aggregate are stored in a database, and only the root should be obtainable through queries. The other objects should be obtained through traversal associations.
  3. and you have invariant rules that u need to enforce uniformly across the contained objects

your scenario doesn't seem to satisfy either of those 2. so my opinion is no

Also read this post and provided answers: DDD: Aggregate Roots

-1
votes

Whether Address should be a separate entity should not be driven by technical concerns.

The way you talk about an address tells me it is a separate entity made up of the constituent parts you mentioned.

The fact that the Address persists even when it isn't tied to a Person or another class, also is a clue that it should be its own entity.

Furthermore: Address can be used not just be a Person, but by other things (classes) as well. Do you really want to burden each class that can have an address to have to deal with how to form it from its consituent parts?

The fact alone that you are talking about an Address as a specific concept is enough to make it a separate class. Even in the case where an address would only exist as long as it is tied to another class, it would make sense to create a separate class, possibly a nested class in that case, just to separate the logic dealing with the address from the logic dealing with the rest of the person's attributes.

Update

If I understand it correctly (http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - the part about aggregates), then whether an address can exist without a person (or other addressee) is irrelevant; the question is whether the address-constituents can exist or be accessed without the address. If they can, Address shouldn't be an aggregate root.

On the one hand an Address should be an aggregate of its constituent parts. But, the constituent parts of an address seem to be independent of address and can exist without it. After all, a municipality or street can exist without a "door" being present in either. So, I would say that this disqualifies Address as an aggregate root in DDD terms.

Update As Tommy mentioned (see comments): A better question would be "Will the system ever manipulate a street/municipality directly, or will it always be the whole address?"

I would consider that selecting a municipality from a list in order to construct an address isn't "direct manipulation" when it is always done in the context of constructing an address. Similarly, I would not consider maintaining that list of municipalities "direct manipulation" if it is only maintained for use by an address.

Update As Arnis points out, whether Address can exist independently of Person (or another entity) is relevant in as much as that dictates whether Address is an entity in its own right. As I understand it now, only entities can be aggregate roots.