views:

116

answers:

3

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?

+1  A: 

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: http://stackoverflow.com/questions/2558469/ddd-aggregate-roots

Pangea
Could you clarify no. 1 please? No. 2 is not totally fulfilled as I would have to store part of the aggregate root in the database, where other properties will be obtained by traversing associations. Do you still think that having an aggregate is wrong? Also, are you sure that an aggregate root is not supposed to be stored in the database? A poster here doesn't seem to agree on that: http://stackoverflow.com/questions/2627772/ddd-persisting-aggregates
Tommy Jakobsen
"Aggregate is a domain pattern used to define object ownership and boundaries." - from domain driven design quickly. I am talking about the ownership part. In your case, seems like the Municipalities and Streets are Entities on their own and hence have their own life-cycle. another way of looking at this is: if you delete an Address, does that mean you should also delete the streets and municipalities associated with it?
Pangea
Actually Municipality, District, Street, HouseNumber are all entities as they are modeling a real world addressing system in this country. And our database will contain an entry in HouseNumber for each "door" in the country (thats how the address system is build by the government). Then we associate a person to an address because he lives there. If he moves, the address is still persisted it's only the relationship between the person and the address thats removed and a new one is created. Do you get the idea? And do you still not think that an aggregate makes any sense?
Tommy Jakobsen
ok i get the idea now and since the Address DOESNT OWN the associated objects, address cant be an aggregate and enforce rules. But I'd also wait for others to comment on this INTERESTING question
Pangea
here is the reference enforcing my thought process: http://thinkddd.com/blog/2009/02/14/aggregates-and-aggregate-roots/
Pangea
Thank you. But if I don't have an aggregate root for these informations, will I need to have a repository for each? Making a total of 5 repositories "just" for handling an address semms like a lot of classes.
Tommy Jakobsen
Maybe this should be modified and address should own associated objects? What about Your domain - is there anything You have to model that works with municipality, district, street, housenumber directly without address participation?
Arnis L.
At the moment no. But if I should think of something that could become an "issue", is when a post office is tied directly to a district. Then it will have a reference to a district in a municipality, and therefore not reference an address (most likely it will have both tho, but it's important to be able to associate a district directly in this scenario).
Tommy Jakobsen
Btw, You shouldn't apply DRY blindly. It **might** make sense that district of post office is not the same what person is associated with. E.g. - if it's in different bounded context.
Arnis L.
I don't think I understood that. Could you give an example? What do you me by "apply DRY blindly"?
Tommy Jakobsen
Just motivating You to think before anything You do. Don't bother. :)
Arnis L.
+3  A: 

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.

Arnis L.
An address is definitely an entity. Addresses exists on their own and if a person move to an address, he gets associated with it. Two persons can be associated to the same address, and if one of them move the other doesn't move automatically. Addresses are the most central object - they exists on their own even if no persons are associated to it (we get them from the government into our database where they are persisted).
Tommy Jakobsen
Regarding the movement process, number 2 is definitely the process. After reading, reading more, and more, i think it makes sense to have address as an aggregate root. Thank you very much for your comments.
Tommy Jakobsen
So something can only be an aggregrate root if it is an entity in its own right. Makes sense.
Marjan Venema
A: 

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.

Marjan Venema
I'm not so concerned about weather an address should be an entity or not. That I'm pretty clear about: it has to be. The really question is if it makes any sense to make it an aggregate root when following DDD principles?
Tommy Jakobsen
@Tommy And answer is - it depends on what You are trying to model. It can be both. :)
Arnis L.
@Arnis Of course, which is what I'm trying to describe in this question - to get your opinion :-)
Tommy Jakobsen
@Tommy: see update
Marjan Venema
Thats an interesting point Marjan. But shouldn't you see this from a bigger picture? Like "Will the system ever manipulate a street/municipality directly, or will it always be the whole address?"
Tommy Jakobsen
@Tommy, yes, I think that is a better way of putting it. In addition I'd say 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.
Marjan Venema
I would like other comments on Marajan's latest update to his answer. It sounds correct to me but then again I'm no DDD expert so a second opinion would be great.
Tommy Jakobsen
Uh, just for the record, I am a she...
Marjan Venema
I kind a disagree. Will update my answer a bit later when I won't feel so lazy. :)
Arnis L.
@Marjan Sorry about that. Thank you Arnis. Looking forward to that :-)
Tommy Jakobsen
Please, see my response.
Arnis L.